develooper Front page | perl.perl5.porters | Postings from June 2022

Pre-RFC: lazy arrays and hashes (maybe scalars?)

Thread Next
From:
Ovid
Date:
June 30, 2022 09:41
Subject:
Pre-RFC: lazy arrays and hashes (maybe scalars?)
Message ID:
CA+M4CHv95nk99D7Dj3XMNuEkBv4qXoZunsH_MGd0tzDQyOY2vQ@mail.gmail.com
Hi all,

Sorry if this has already been discussed.

Just a wild idea, but I would love the idea of being able to mark a
variable as "lazy" with a generator function. No idea what the syntax would
be, but something like this:

    sub fib ($index) {
        return $index if $index == 0 or $index == 1;
        return fib($index-1)+fib($index-2);
   }
    my @fibonacci_numbers :lazy \&fib;
    say $fibonacci[7]; # prints 21, the eighth fibonacci number

Any variable marked as :lazy would behave just like a regular variable, but
the values would not be calculated until that variable is accessed. In the
above example, nothing is computed until you access an element. When you
do, the fib() subroutine is called with the index (7, in this case).
Subsequent accesses to that element do not call the fib() function.

Because Perl doesn't distinguish between uninitialized and undefined, the
above would also need to call fib() with the values 0 through 7. If we
*could* distinguish between uninitialized and defined, we could ask for an
arbitrary element and the rest could remain undefined (this would be very
useful for cases where the values can be calculated independently). This is
one case where using a hash over an array would definitely be a win.

$#fibonacci = 7 would force the array size and call the generator function
for indexes 0 .. 7. $fibonacci[7] = 23 would do the same thing, but
allowing the developer to set their own values (even if wrong).

You could precompute some numbers, too:

    my @fibonacci_numbers :lazy \&fib = qw/1 1 2 3 5 8 13 21 34 55/;

With the above, the first 10 fibonacci numbers are assigned and fib() is
not called for them. The others will be filled in, but only if accessed

For hashes:

    use LWP::Simple 'get';

    my %html_for :lazy \&get = ('https://www.example.com/' => undef);
    say $html_for{'https://www.example.com/'}; # prints undef because the
key already exists
    say $html_for{'https://other.side/'};      # attempts to fetch the html

In that example, instead of a numeric index, we call get() with the hash
key, but only if that key does not exist.

Best,
Curtis "Ovid" Poe
CTO, All Around the World
World-class software development and consulting
https://allaroundtheworld.fr/

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About