File Coverage

blib/lib/Scalar/Lazy.pm
Criterion Covered Total %
statement 25 25 100.0
branch 2 2 100.0
condition n/a
subroutine 8 8 100.0
pod 3 3 100.0
total 38 38 100.0


line stmt bran cond sub pod time code
1             package Scalar::Lazy;
2 5     5   174884 use warnings;
  5         11  
  5         254  
3 5     5   29 use strict;
  5         8  
  5         378  
4             our $VERSION = sprintf "%d.%02d", q$Revision: 0.3 $ =~ /(\d+)/g;
5 5     5   29 use base 'Exporter';
  5         16  
  5         1853  
6             our @EXPORT = qw/ delay lazy /;
7              
8             sub new($&;$) {
9 417     417 1 573 my ($pkg, $code, $init) = @_;
10 417 100       813 if ($init){
11 1         19 my $val = $code->();
12 1     2   7 $code = sub { $val };
  2         6  
13             }
14 417         1715 bless $code, $pkg;
15             }
16              
17 417     417 1 5196 sub lazy(&;$) { __PACKAGE__->new(@_) }
18             *delay = \&lazy;
19              
20             sub force($){
21 1741     1741 1 10424 my $pkg = ref $_[0];
22 1741         3406 bless $_[0], $pkg . '::FORCE';
23 1741         3168 my $val = $_[0]->();
24 1741         4664 bless $_[0], $pkg;
25 1741         3361 $val;
26             }
27              
28             use overload (
29 40         97 fallback => 1,
30 5         15 map { $_ => \&force } qw( bool "" 0+ ${} @{} %{} &{} *{} )
31 5     5   10729 );
  5         8903  
32              
33             1; # End of Scalar::Lazy
34              
35             =head1 NAME
36              
37             Scalar::Lazy - Yet another lazy evaluation in Perl
38              
39             =head1 VERSION
40              
41             $Id: Lazy.pm,v 0.3 2008/06/01 17:09:08 dankogai Exp dankogai $
42              
43             =head1 SYNOPSIS
44              
45             use Scalar::Lazy;
46             my $scalar = lazy { 1 };
47             print $scalar; # you don't have to force
48              
49             # Y-combinator made easy
50             my $zm = sub { my $f = shift;
51             sub { my $x = shift;
52             lazy { $f->($x->($x)) }
53             }->(sub { my $x = shift;
54             lazy { $f->($x->($x)) }
55             })};
56             my $fact = $zm->(sub { my $f = shift;
57             sub { my $n = shift;
58             $n < 2 ? 1 : $n * $f->($n - 1) } });
59             print $fact->(10); # 3628800
60              
61             =head1 DISCUSSION
62              
63             The classical way to implement lazy evaluation in an eager-evaluating
64             languages (including perl, of course) is to wrap the value with a closure:
65              
66             sub delay{
67             my $value = shift;
68             sub { $value }
69             }
70             my $l = delay(42);
71              
72             Then evaluate the closure whenever you need it.
73              
74             my $v = $l->();
75              
76             Marking the variable lazy can be easier with prototypes:
77              
78             sub delay(&){ $_[0] }
79             my $l = delay { 42 }
80              
81             But forcing the value is pain in the neck.
82              
83             This module makes it easier by making the value auto-forcing.
84              
85             =head2 HOW IT WORKS
86              
87             Check the source. That's what the source is for.
88              
89             There are various CPAN modules that does what this does. But I found
90             others too complicated. Hey, the whole code is only 25 lines long!
91             (Well, was until 0.03) Nicely fits in a good-old terminal screen.
92              
93             The closest module is L, a brainchild of Audrey Tang.
94             But I didn't like the way it (ab)?uses namespace.
95              
96             L depends too many modules.
97              
98             And L is overkill.
99              
100             All I needed was auto-forcing and this module does just that.
101              
102             =head1 EXPORT
103              
104             C and C.
105              
106             =head1 FUNCTIONS
107              
108             =head2 lazy
109              
110             lazy { value }
111              
112             is really:
113              
114             Scalar::Lazy->new(sub { value });
115              
116             You can optionally set the second parameter. If set, the value
117             becomes constant. The folloing example illustrates the difference.
118              
119             my $x = 0;
120             my $once = lazy { ++$x } 'init'; # $once is always 1
121             is $once, 1, 'once';
122             is $once, 1, 'once';
123             my $succ = lazy { ++$x }; # $succ always increments $x
124             isnt $succ, 1, 'succ';
125             is $succ, 3, 'succ';
126              
127             =head2 delay
128              
129             an alias to L.
130              
131             =head1 METHODS
132              
133             =head2 new
134              
135             Makes a lazy variable which auto-forces on demand.
136              
137             =head2 force
138              
139             You don't really need to call this method (that's the whole point of this
140             module!) but if you want, you can
141              
142             my $l = lazy { 1 };
143             my $v = $l->force;
144              
145             =head1 AUTHOR
146              
147             Dan Kogai, C<< >>
148              
149             =head1 BUGS
150              
151             Please report any bugs or feature requests to C, or through
152             the web interface at L. I will be notified, and then you'll
153             automatically be notified of progress on your bug as I make changes.
154              
155             =head1 SUPPORT
156              
157             You can find documentation for this module with the perldoc command.
158              
159             perldoc Scalar::Lazy
160              
161             You can also look for information at:
162              
163             =over 4
164              
165             =item * RT: CPAN's request tracker
166              
167             L
168              
169             =item * AnnoCPAN: Annotated CPAN documentation
170              
171             L
172              
173             =item * CPAN Ratings
174              
175             L
176              
177             =item * Search CPAN
178              
179             L
180              
181             =back
182              
183             =head1 ACKNOWLEDGEMENTS
184              
185             Highly inspired by L by Audrey Tang.
186              
187             =head1 COPYRIGHT & LICENSE
188              
189             Copyright 2008 Dan Kogai, all rights reserved.
190              
191             This program is free software; you can redistribute it and/or modify it
192             under the same terms as Perl itself.
193              
194              
195             =cut