我发现Haskell和Perl6最有趣的特性之一是能够推迟计算值,直到实际需要它们为止。
另一方面,Perl5喜欢立即做所有事情,但据我所知,它包含了懒惰评估的所有必要原语。那些是:@_
会创建一个数组引用,该引用的别名是其参数列表中的标识符,即使其中一些标识符尚未包含值。\@_
的子例程中返回重载/绑定对象,然后在需要时取消引用它。 (并且有各种CPAN模块可以抽象出领带/过载细节)我一直在Perl中尝试各种懒惰的编程技术(我在工作中有一个模块,它在Perl5中实现了相当多的Haskell Prelude(像共同递归:$_ = list 0, 1, zipWith {&sum} $_, tail $_ for my $fibs;
来定义Fibonacci顺序已经工作))。但我觉得代码中隐藏着一些微妙的错误,这些错误可能会在函数用于较大的表达式/程序时出现。
所以我想知道是否有任何好的例子(CPAN /博客/书籍),任何人都知道在Perl5中使用Haskell / Perl6就像懒惰一样?特别是,我想阅读使用这种懒惰的任何重要代码。
我也有兴趣知道是否有人遇到任何关于Perl 5中延迟评估实现的问题或棘手的问题。
答案 0 :(得分:9)
高阶Perl(免费提供online)有一章叫做“Infinite Streams”。也许这是一个很好的起点。
答案 1 :(得分:6)
好吧,Moose通过lazy loading of attributes执行此操作:
默认和构建器方法
属性可以有默认值,Moose提供了两种指定默认值的方法 [描述了“默认”和“构建器”选项...]<强>懒惰强>
Moose允许您通过使属性“懒惰”来推迟属性填充:has 'size' => ( is => 'ro', lazy => 1, builder => '_build_size', );
当“lazy”为真时,在调用reader方法之前不会生成默认值,而不是在对象构造时生成。有几个原因 你可能会选择这样做。
首先,如果此属性的默认值取决于某些其他属性,则该属性必须为“lazy”。在对象构造期间,默认值 不是以可预测的顺序生成的,因此在生成默认值时,您不能指望正在填充的其他属性。
其次,在需要之前通常没有理由计算默认值。使属性“延迟”可以将成本推迟到属性之前 需要。如果永远不需要该属性,则可以节省一些CPU时间。
我们建议您使用构建器或非平凡的默认“懒惰”来创建任何属性。
答案 2 :(得分:4)
我认为最大的问题是“魔法的冲突”。当你想要做一些你觉得很漂亮的事情时,其他一些模块作者正在尝试他们认为很漂亮的东西,结果是不确定的。谁的魔法赢了?
由于人们总是可以窥探另一个变量的魔力,或者甚至无意中将其贬低,因此魔法并不是防弹的。
如果你能通过详尽的案例测试达到100%的正交性,你可能会更容易......也许。