The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Scalar::Lazy - Yet another lazy evaluation in Perl

VERSION

$Id: Lazy.pm,v 0.3 2008/06/01 17:09:08 dankogai Exp dankogai $

SYNOPSIS

use Scalar::Lazy;
my $scalar = lazy { 1 };
print $scalar; # you don't have to force

# Y-combinator made easy
my $zm = sub { my $f = shift;
               sub { my $x = shift; 
                     lazy { $f->($x->($x)) }
                 }->(sub { my $x = shift; 
                           lazy { $f->($x->($x)) }
                       })};
my $fact = $zm->(sub { my $f = shift;
                       sub { my $n = shift;
                             $n < 2  ? 1 : $n * $f->($n - 1) } });
print $fact->(10); # 3628800

DISCUSSION

The classical way to implement lazy evaluation in an eager-evaluating languages (including perl, of course) is to wrap the value with a closure:

sub delay{
  my $value = shift;
  sub { $value }
}
my $l = delay(42);

Then evaluate the closure whenever you need it.

my $v = $l->();

Marking the variable lazy can be easier with prototypes:

sub delay(&){ $_[0] }
my $l = delay { 42 }

But forcing the value is pain in the neck.

This module makes it easier by making the value auto-forcing.

HOW IT WORKS

Check the source. That's what the source is for.

There are various CPAN modules that does what this does. But I found others too complicated. Hey, the whole code is only 25 lines long! (Well, was until 0.03) Nicely fits in a good-old terminal screen.

The closest module is Scalar::Defer, a brainchild of Audrey Tang. But I didn't like the way it (ab)?uses namespace.

Data::Thunk depends too many modules.

And Data::Lazy is overkill.

All I needed was auto-forcing and this module does just that.

EXPORT

lazy and delay.

FUNCTIONS

lazy

lazy { value }

is really:

Scalar::Lazy->new(sub { value });

You can optionally set the second parameter. If set, the value becomes constant. The folloing example illustrates the difference.

my $x = 0;
my $once = lazy { ++$x } 'init'; # $once is always 1
is $once, 1, 'once';
is $once, 1, 'once';
my $succ = lazy { ++$x }; # $succ always increments $x
isnt $succ, 1, 'succ';
is $succ, 3, 'succ';

delay

an alias to "lazy".

METHODS

new

Makes a lazy variable which auto-forces on demand.

force

You don't really need to call this method (that's the whole point of this module!) but if you want, you can

my $l = lazy { 1 };
my $v = $l->force;

AUTHOR

Dan Kogai, <dankogai at dan.co.jp>

BUGS

Please report any bugs or feature requests to bug-scalar-lazy at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Scalar-Lazy. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

SUPPORT

You can find documentation for this module with the perldoc command.

perldoc Scalar::Lazy

You can also look for information at:

ACKNOWLEDGEMENTS

Highly inspired by Scalar::Defer by Audrey Tang.

COPYRIGHT & LICENSE

Copyright 2008 Dan Kogai, all rights reserved.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.