我有这段代码.第一个非嵌套map
输出一些东西,嵌套一个没有.我想我理解为什么第二个不起作用.这是一个懒惰的序列,Perl 6正在收集结果.没关系.但是不是第一个(非嵌套)map
以同样的方式懒惰吗?如果我不对地图的结果做任何事情,它如何输出任何内容?也就是说,第一个人怎么懒?是否会自动获取接收器上下文,我必须明确sink
地为嵌套的上下文提供(或某些东西)?不知怎的,我认为Perl 6应该能够为我解决这个问题.
my @array = (1, 2), (3, 4), ('a', 'b'); say "---On its own:"; my @item = 1, 2, 3; @item.map: { say $_; }; say "---Inside another map:"; @array.map: { my @item = 1, 2, 3; @item.map: { say $_; } };
这是输出:
---On its own: 1 2 3 ---Inside another map:
这与问题如何在Perl 6中的"for"循环中使用"map"这个问题有关?.那个人说要做什么,但我问的更多是为什么问题.
在这方面,该解决方案是添加eager
,sink
或分配给内部map
:
say "---eager:"; @array.map: { my @item = 1, 2, 3; eager @item.map: { say $_; } }; say "---sink:"; @array.map: { my @item = 1, 2, 3; sink @item.map: { say $_; } }; say "---assignment:"; @array.map: { my @item = 1, 2, 3; @ = @item.map: { say $_; } };
smls.. 8
每个程序文件,块,子例程等的内容都是由"以分号分隔的1个语句组成"的"语句列表" .考虑到这一点:
沉没的陈述:
声明列表中的最后声明除外.
任何循环语句(for
,while
,等2)在语句列表级别3,即使是最后一个.
程序或模块文件的顶级语句列表中的任何语句,即使它是最后一个语句.4
返回而不是沉没的语句:
声明列表中的最终声明,但上述情况除外.
下沉力量急切评价,回归没有.
在您的情况下,第一个map
语句位于语句列表的中间,因此它会被沉没.
但是嵌套map
语句是其语句列表的最终语句,因此其结果将以尚未迭代的形式返回Seq
.
它的父map
语句也是一个最终语句,但它位于程序文件的顶级语句列表中,因此它会被沉没,导致它急切地迭代由三个Seq
值组成的序列.(say
在内部之前插入一个语句map
,看看这个.)
但是没有任何东西会沉没或以其他方式迭代这三个内在Seq
值中的每一个.
更详细地说,来自概要04,第664行:
在任何语句序列中,只返回最终语句的值,因此所有先前语句都在接收器上下文中进行评估,这是自动急于求助,以强制评估副作用.(副作用是首先执行此类语句的唯一原因,事实上,如果您在接收器上下文中执行"无用"操作,Perl将警告您.)接收器上下文中的循环不仅会热切地评估自己,但可以优化循环中任何值的产生.
语句列表的最终语句不是接收器上下文,并且可以返回任何值,包括惰性列表.但是,为了支持命令式程序员的期望(我们绝大多数人,事实证明),任何显式循环作为语句列表的最终语句被自动强制使用接收器语义,以便循环执行完成后再返回块.
此强制接收上下文仅在语句列表级别(即编译单元的顶级)或直接在块内部应用于循环.假定将单个语句或semilist解析为参数的构造函数需要该语句的结果,因此即使该语句是循环,此类构造仍然是惰性的.
1)当一个右括号}
出现在一行的最后一个正确的标记时,因为
my @a = @b.map: { $_ + 1 } # whitespace/comment doesn't count
它也结束了当前的语句,但是否则需要一个分号来分隔语句.
2)map
不计数,因为它是一个函数而不是循环关键字.
3)意味着当一个循环语句出现在一个不同的地方而不是直接出现在一个语句列表中时,例如
lazy for ^10 { .say } # as argument to a keyword expecting a single statement
(for ^10 { .say }) # inside an expression
它默认情况下不会被沉没.这就是概要引言的最后一段试图说的.
更新:在Rakudo中似乎并非如此,但这可能是一个错误.
4)在概要中没有提到这个规则,但是它在Rakudo中是如何工作的,我很确定它是故意的.
每个程序文件,块,子例程等的内容都是由"以分号分隔的1个语句组成"的"语句列表" .考虑到这一点:
沉没的陈述:
声明列表中的最后声明除外.
任何循环语句(for
,while
,等2)在语句列表级别3,即使是最后一个.
程序或模块文件的顶级语句列表中的任何语句,即使它是最后一个语句.4
返回而不是沉没的语句:
声明列表中的最终声明,但上述情况除外.
下沉力量急切评价,回归没有.
在您的情况下,第一个map
语句位于语句列表的中间,因此它会被沉没.
但是嵌套map
语句是其语句列表的最终语句,因此其结果将以尚未迭代的形式返回Seq
.
它的父map
语句也是一个最终语句,但它位于程序文件的顶级语句列表中,因此它会被沉没,导致它急切地迭代由三个Seq
值组成的序列.(say
在内部之前插入一个语句map
,看看这个.)
但是没有任何东西会沉没或以其他方式迭代这三个内在Seq
值中的每一个.
更详细地说,来自概要04,第664行:
在任何语句序列中,只返回最终语句的值,因此所有先前语句都在接收器上下文中进行评估,这是自动急于求助,以强制评估副作用.(副作用是首先执行此类语句的唯一原因,事实上,如果您在接收器上下文中执行"无用"操作,Perl将警告您.)接收器上下文中的循环不仅会热切地评估自己,但可以优化循环中任何值的产生.
语句列表的最终语句不是接收器上下文,并且可以返回任何值,包括惰性列表.但是,为了支持命令式程序员的期望(我们绝大多数人,事实证明),任何显式循环作为语句列表的最终语句被自动强制使用接收器语义,以便循环执行完成后再返回块.
此强制接收上下文仅在语句列表级别(即编译单元的顶级)或直接在块内部应用于循环.假定将单个语句或semilist解析为参数的构造函数需要该语句的结果,因此即使该语句是循环,此类构造仍然是惰性的.
1)当一个右括号}
出现在一行的最后一个正确的标记时,因为
my @a = @b.map: { $_ + 1 } # whitespace/comment doesn't count
它也结束了当前的语句,但是否则需要一个分号来分隔语句.
2)map
不计数,因为它是一个函数而不是循环关键字.
3)意味着当一个循环语句出现在一个不同的地方而不是直接出现在一个语句列表中时,例如
lazy for ^10 { .say } # as argument to a keyword expecting a single statement
(for ^10 { .say }) # inside an expression
它默认情况下不会被沉没.这就是概要引言的最后一段试图说的.
更新:在Rakudo中似乎并非如此,但这可能是一个错误.
4)在概要中没有提到这个规则,但是它在Rakudo中是如何工作的,我很确定它是故意的.
.map基本上返回一个.Seq.会发生的事情是内部地图将Seq返回到外部地图,但由于该地图的结果是沉没的,因此它们会在不进行迭代的情况下消失.
如果你说外部地图,你将拉出内部地图的结果,你会看到返回内部地图的.Seq的结果:
my @array = (1, 2), (3, 4), ('a', 'b'); say "---Inside another map:"; say @array.map: { my @item = 1, 2, 3; @item.map: { say $_; } } ---Inside another map: 1 2 3 1 2 3 1 2 3 ((True True True) (True True True) (True True True))
希望有道理:-)
另一种解决方案是将特定的返回值添加到外部地图.然后内部地图将被沉没,因此迭代,如下所示:
my @array = (1, 2), (3, 4), ('a', 'b'); say "---Inside another map:"; say @array.map: { my @item = 1, 2, 3; @item.map: { say $_; } 42 # make sure ^^ map is sunk } ---Inside another map: 1 2 3 1 2 3 1 2 3