📄 promise.pm
字号:
# Copyright 2001-2005 Six Apart.# SCRiPTMAFiA 2005 - THE DiRTY HANDS ON YOUR SCRiPTS## $Id: Promise.pm 10802 2005-03-29 02:46:37Z ezra $package MT::Promise;use strict;use Exporter;*import = \&Exporter::import;@MT::Promise::EXPORT_OK = qw(delay force lazy);sub new { my ($class, $code) = @_; my $this = \$code; bless $this, $class;}sub delay { my ($this) = @_; __PACKAGE__->new($this);}sub lazy (&) { my ($this) = @_; __PACKAGE__->new($this); }sub force { my ($this) = @_; return $this if (ref $this ne 'MT::Promise'); if (ref $$this eq 'CODE') { $$this = $$this->(); } else { return $$this; } }1;__END__=head1 NAMEMT::Promise - Faux-lazy evaluation for Perl=head1 SYNOPSIS sub work_hard { # some costly operation } use MT::Promise qw(delay lazy force); # slickest $meaning_of_life = lazy { work_hard(); return 42 }; # kinda slick $meaning_of_life = delay(sub { work_hard(); return 42 }); # clunky ... $meaning_of_life = new MT::promise(sub { work_hard(); return 42; }); print force($meaning_of_life); # prints: # 42 =head1 DESCRIPTIONA promise is like a value, but the value itself hasn't been computedyet. At any time, you can "force" the promise to get its value; thefirst time it's forced, the computation of the value takes place andthe value is stored. Thereafter, forcing it uses the stored valueinstead of re-computing it.This is useful if some bit of code may be expecting a value in acertain place, but you don't know up front whether that value willreally be needed. To use this optimization, the expectant code needsto expect a promise, of course, since it has to call C<force> to getthe value. But you don't have to worry about whether the value will beneeded or which bit of code will need it first--that will shake out atruntime.=head1 USAGEThere are three forms for creating promises. The C<lazy> form is the slickest: my $red = foo($arg); my $value = lazy { $green = green($red); $blue = blue($red, $green); }The C<delay> form can be useful if you want to delay the evaluation ofa routine that already has a name: my $value = delay \&costly_function;but it should be pointed out that costly_function in this case must bea thunk--it must not expect any arguments. Typically, you end upusing a closure or the C<lazy> form to encapsulate the arguments: my $value1 = lazy { fibonacci(8675309) };This is almost precisely like $value2 = fibonacci(865309) except that(a) you have to force $value1, and (b) the 8675309th fibonacci won'tbe calculated if it's never C<force>d.Last and least, you can use C<new> to create a promise, though it'sclunkier than the other methods: my $value = new MT::Promise(sub { fibonacci(8675309) });This would be useful if you were sub-classing promise for some reason.=head1 NOTESNote that if you use the name of a variable declared outside the lazyblock, such as my $red; my $value = lazy { foo($red) }then $value will carry around a reference to $red for as long as$value lives. This is important to keep in mind as it's possible tocreate a circular reference without realizing it. You've got to trypretty hard, though.=cut
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -