取势 明道 优术

有用的和有意思的循环 2,219 views

作者为 扶 凯 发表

我们常使用的任何语言,我们都知道循环非常的有用,在语言提供这些功能,我们常用象 foreach 之类的循环来从数组或者列表的开始到结束.在 Perl 5 中,提供了 foreach 的关键字,当然你也能写成 for 的关键字来实现象 C 风格的循环.
在 Perl 6 中,这些全都改变了.
现在 for 是专用来进行列表的迭代.foreach 就不在使用了.那个 C 风格的循环处理使用了新的关键字 loop.我们今天并不讨论这个东西.我们今天的焦点是新的循环.我们结合一些其它的 Perl 6 语言的特性来实现非常灵活又强大的概念.
让我们来看一个基本的例子.

for 1, 2, 3, 4 { .say }

这是一个最简单清晰的语法的例子.在这并没有使用括号来包起整个列表的语句,象这种写法可以贯穿整个 Perl 6. 通常比起 Perl 5 来你没有必要写那么多的括号了.很象 Perl 5 .这个循环中的值会默认存到 $_ .在这个方法调用的 say 其实就是 $_.say.注意在 Perl 6 中,你不能直接只打一个 say 的调用而不加参数,认为会默认使用 $_ 来传参.你需要使用 .say 要么明确的指定是 $_.
这个语法块并不是一个普通的块.它能通过一个尖的指向,来告诉你的循环变量传进去的参数的名字.

for 1, 2, 3, 4 -> $i { $i.say }

这个尖的指向有点象匿名的子函数.除了它不能取得返回的例外.如果你调用的 return 内部有这个,将返回闭合的子函数.
这个尖尖也能取多个参数.象下面这样.

> for 1, 2, 3, 4 -> $i, $j { "$i, $j".say }
1 2
3 4

实际做了些什么啦?就是你在列表进行迭代时一次取了两个元素.这个可以在任何数字的参数下正常工作,最小一个参数.如果你不明确指明参数的话,就退化到 Perl 5 一样使用 $_.
我们可以意识到这个我们能做什么,比如迭代一个列表中?当然,也可以是一个数组的值.

for @array { .say }

这是一个非常简单的例子,我们可能更加喜欢使用 map:

@array.map: *.say;

如果对你来讲顺序和连续的并不重要,你可以使用 hyperoperator(超),上一个文章中也讲过这个,今天的主题也不详细讲这个了.

@array».say;

我们也能使用范围构造器中缀的 <..> 来生成一个数字的列表:

for 1..4 { .say }

有一个最通用的功能,就是我们想些生成一个从 0 开始到 $n 的数字的列表,比如常用的数组下标.我们可以写成 0 .. $n-1或者另一个不同的范围构造器 0..^$n.但在 Perl 6 中提供了一个短的快捷的方法就是使用前缀的 <^>.

>for ^4 { .say }
0
1
2
3

一个常用的理由是,人们在 Perl 5 中常常退回到 C 风格的循环的原因是必须知道 for 的成员数组中索引的位置,或者因为必须并行的迭代二个和更多的数组.Perl 6 提供了一个短的快捷方法,就是中缀的 <Z> 这个 zip 操作符.

for @array1 Z @array2 -> $one, $two { ... }

假设二个数组是相同的长度$one 会是第一个 @array1 的成员元素,$two 会是相应的位置 @array2 的成员元素.如果是不同的长度的话.迭代会停止到短的那个数组结束的长度.

了解这方面的知识,并认识到 Perl 6 的懒的列表产生,我们可以很容易地在迭代数组包含进索引:

for ^Inf Z @array -> $index, $item { ... }

如果一个无限长的列表,会让你使用上面害怕的话,可以象下面这样,使用前缀操作符 ^ 来取出数组元素的长度.

for ^@array.elems Z @array -> $index, $item { ... }

上面这个可以得到相同的结果,但是更加优雅.因为中缀操作符 Z 操作时,第一个元素的长度决定了什么整个长度.

for @array.kv -> $index, $item { ... }

@array.kv 会返回 keys 和 values 的交错,这个 $key 是数组元素的下标.所以同时迭代这二个可能是你比较想要的效果.

希望这篇文章让你了解 Perl 6 灵活的循环相关的一些概念,它们可以灵活的使用在各种常见任务上.在这之前,我要回答最后一个问题,我知道有人一直在想这个问题.怎么样一次性迭代四个数组.

for @one Z @two Z @three Z @four -> $one, $two, $three, $four { ... }

这是一个关联列表中缀操作符,这样使用,是不是一种享受?

来了就留个评论吧! 4个评论



    Nam 2011年10月30日 的 05:34

    Perl6 是一种享受

    page 2011年11月5日 的 04:07

    我正在学Perl6 ,谢谢

    p 2011年11月9日 的 04:01

    一点点模模糊糊的细节。
    我可能要细细品味。
    谢谢。

    asdfghjkl 2012年04月17日 的 03:54

    for @one Z @two Z @three Z @four -> $one, $two, $three, $four { … }
    太丑了!