Perl 6圣诞月历 (2011)

2011


The Flip-Flop operator


Perl5有一个二元操作符叫做flip-flop,它为假直到它的第一个参数被计算为真,然后它保持真(反转),直到第二个参数计算为真,然后在那里它又变成假(flop)。 这真是太有用了,以至于Perl6也有flip-flop,只是它拼写为ff,并有一些变异:

    ff
    ff^
    ^ff
    ^ff^

音调符号^意味着在那个结尾跳过结尾。
…或许一些例子更能说明问题…

for 1..20 { .say if $_ == 9  ff  $_ == 13; }     # 9 10 11 12 13
for 1..20 { .say if $_ == 9  ff^ $_ == 13; }     # 9 10 11 12
for 1..20 { .say if $_ == 9 ^ff  $_ == 13; }     # 10 11 12 13
for 1..20 { .say if $_ == 9 ^ff^ $_ == 13; }     # 10 11 12

每个例子中,我们遍历从1到20的数字范围,并且在flip-flop返回真时输出那些数字。每次循环中,flip-flop 操作符的左边($_ == 9) 和 flip-flop操作符的右边 ($_ == 13)都会被计算。 (这里我已经在 flip-flop操作符的两侧使用了简单的数字比较,但是,一般任何布尔表达式都能使用。

每个 flip-flop 操作符的实例维护它们的内部状态以决定什么时候返回TRUE或False.所有的flip-flop操作符在它们的内部状态被设置为返回False时出现,直到它们被反转然后开始返回 TRUE.

在第一个和第二个例子中,当$_ == 9 时,flip-flop 操作符反转它们的内部状态为 TRUE ,然后立即返回 TRUE.在第三个和第四个例子中,当$_== 9时,flip-flop操作符将它们的内部状态设置为 TRUE,但是它们在那次遍历中返回 False ,因为前置的 ^符号。
类似地,在上面的第一个和第三个例子中,一旦RHS求值为真时, flip-flop操作符在下一次循环中将它们的内部状态反转回FALSE,然后返回True.在第三个和第四个例子中,flip-flop操作符在RHS返回真时立即反转为FALSE.
让flip-flop操作符反转但从不flop,在RHS上使用*:

    for 1..20 { .say if $_ == 15 ff *; }     # 15 16 17 18 19 20

Perl6有另外一套 flip-flop操作符,功能与上面提到的差不多,除了,在LHS变成真的时候,RHS不被求值。这很有用,当flip-flop操作符的RHS 和LHS 都同时求值为真的时候,These operators are spelled 这些操作符被拼写为 fff, fff^, ^fff, and fff.

Idiomatic Perl 6


December 23, 2011

下面大多数的例子使用 4 种版本展示代码:

  • Non-idiomatic Perl 5,
  • then made idiomatic.
  • Perl 5 idiom, naively translated into Perl 6,
  • then made idiomatic.

从 1 到 4 越来越清晰和简洁

  • 随机选择数组元素
$z = $array[ int(rand scalar(@array)) ];
$z = $array[ rand @array ];
$z = @array[ rand*@array ];
$z = @array.pick;
  • 循环遍历数组的键(索引)
for ( my $i=0; $i<@array; $i++ ) {...}
for my $i ( 0 .. $#array )       {...}
for 0 .. @array.end -> $i {...}
for @array.keys -> $i     {...}
  • 整除
( ($x - ($x % 3) ) / 3 )
int( $x / 3 )
Int( $x / 3 )   # 首字母需大写
$x div 3        # 整除运算符
  • 打印数组元素的个数
say scalar @array;
say 0+@array;
say 0+@array;          # Identical in Perl 6
say +@array;           # + 强制新的“数值”上下文
say @array.elems;      # .elems 方法更清楚.
  • 每隔5 次 做些事情
if ( ($x/5) == int($x/5) ) {...}
if ( !($x % 5) )           {...}
if !($x % 5) {...}
if $x %% 5   {...}     # %% means "is evenly divisible by"
  • Do something $n times, 直到 $n-1
for ( $_=0; $_ < $n; $_++ ) {...}
for ( 0 .. ($n-1) )         {...}
for 0 ..^ $n {...}
for ^$n      {...}     # ^9 means 0 ..^ 9, or 0..8

eg:

> .say for ^5

0
1
2
3
4

Bare method calls are always methods on $, eliminating Perl 5's confusion on which functions default to $.

  • 按空白分割
@words = split /\s+/, $_;
@words = split;           # Default is useful, but not intuitive
@words = .split(/\s+/);  # split() 现在没有默认的模式
@words = .words;         # split 的旧的行为现在成为了一个单独的方法.words
  • 将字符串分割成单独的字符
@chars = map { substr $word, $_, 1 } 0..length($word);
@chars = split '', $word;# Split on nothingness
@chars = $word.split('');
@chars = $word.comb;     # Default is to "keep everything"

eg:

> my $word='Perl6'
Perl6
> my @chars=$word.split('')
P e r l 6
> my @chars=$word.split('').join('->')
P->e->r->l->6
> my @chars=$word.comb
P e r l 6
> my @chars=$word.comb.join(':')
P:e:r:l:6
  • 无限循环
for (;;)  {...}    # Spoken with a 'C' accent
while (1) {...}
while 1   {...}
loop      {...}   # 没有给出限定条件,所以默认无止尽
  • 按原来的顺序返回列表中的唯一元素
my %s, @r; for @a  { push @r, $_ if !$s{$_}; $s{$_}++; } return @r;
my %s; return grep { !$s{$_}++ } @a;    # or List::MoreUtils::uniq
my %s; return grep { !%s{$_}++ }, @a;
return @a.uniq;
  • 将列表中的所有元素求和
my $sum = 0; for my $num (@a) { $sum += $num }
my $sum; $sum += $_ for @a;    # or List::Util::sum
my $sum = @a.reduce(*+*);
my $sum = [+] @a;              # [op] 将op操作符应用到整个列表
@alpha = 'A' .. 'Z';
@a = qw{ able baker charlie };
%meta = ( foo => 'bar', baz => 'quz' );
@squares = map { $_ * $_ }, @a;
@starts_with_number = grep { /^\d/ }, @a;

钻石操作符还在:

  • Process each line from STDIN or from command-line files.
for my $file (@ARGV) { open FH, $file; while (<FH>) {...} }
while (<>) {...}               # Null filehandle is magical
for $*ARGFILES.lines {...}
for lines()          {...}     # lines() defaults to $fh = $*ARGFILES
  • 将散列初始化为一个常量
my %h;   for (@a) { $h{$_} = 1 }
my %h = map { $_ => 1 } @a;
my %h = map { $_ => 1 }, @a;
my %h = @a X=> 1;

eg:

> my @a=<Perl Python Ruby Perl6>
Perl Python Ruby Perl6
> my %h= @a X=> 1
("Perl" => 1, "Python" => 1, "Ruby" => 1, "Perl6" => 1).hash
  • Hash initialization for enumeration
my %h;   for (0..$#a) { $h{ $a[$_] } = $_ }
my $c;   my %h = map  { $_ => ++$c } @a;
my $c;   my %h = map { $_ => ++$c }, @a;
("Perl" => 1, "Python" => 2, "Ruby" => 3, "Perl6" => 4).hash
my %h = @a Z=> 1..*;       # ("Perl" => 1, "Python" => 2, "Ruby" => 3, "Perl6" => 4).hash
my %h = @a.pairs».invert;  # if zero based , ("Perl" => 0, "Python" => 1, "Ruby" => 2, "Perl6" => 3).hash

@a.pairs
0 => "Perl" 1 => "Python" 2 => "Ruby" 3 => "Perl6"

  • Hash initialization from parallel arrays
my %h;   for (@a) { $h{$_} = shift @b }
my %h;   @h{@a} = @b;
my %h;   %h{@a} = @b;
my %h = @a Z=> @b;

eg:

> my @b=<Larry Gao Mztiz Larry_Wall>
Larry Gao Mztiz Larry_Wall
> my %h= @a Z=> @b
("Perl" => "Larry", "Python" => "Gao", "Ruby" => "Mztiz", "Perl6" => "Larry_Wall").hash
  • 交换两个变量
my $temp = $x; $x = $y; $y = $temp;
( $x, $y ) = ( $y, $x );
 ( $x, $y )  = $y, $x;
 ( $x, $y ) .= reverse;   # .= makes reverse into a "mutating" method
 # Tastes great on array swaps, too!   @a[ $j, $k ] .= reverse;
  • Rotate array left by 1 element
my $temp = shift @a; push @a, $temp;
push @a, shift @a;
@a.push: @a.shift;
@a .= rotate; # Python Ruby Perl6 Perl
  • 创建一个对象
my $pet = new Dog;
my $pet = Dog->new;
my $pet = Dog.new;
my Dog $pet .= new;    # $pet *always* isa Dog; Compiler can optimize!

Combining transformation with selection was an advanced idiom in Perl 5. The new return values for if provide a bite-sized idiom.

  • Three copies of elements > 5
 @z = map { ($_) x 3 } grep { $_ > 5 } @y;    # map,grep
 @z = map { $_ > 5 ? ($_) x 3 : () } @y;      # map as grep
@z = map { $_ > 5 ?? ($_) xx 3 !! Nil }, @y;
@z = @y.map: { $_ xx 3 if $_ > 5 };          # !if == Empty list
@z = ($_ xx 3 if $_ > 5 for @y);             # List comprehension
  • 3到7之间的随机整数,包含3和7
do { $z = int rand 8 } until $z >= 3;
$z = 3 + int rand 5;
$z = 3 + Int(5.rand);
$z = (3..7).pick;
  • 在无限循环中每次循环加 3
for ( my $i = 1; ; $i++ ) { my $n = 3 * $i; ... }
for ( my $n = 3; ; $n += 3 ) {...}
loop ( my $n = 3; ; $n += 3 ) {...}
for 3, * + 3 ... * -> $n      {...}      # `...` is the "sequence" operator
for 3, 6, 9 ... * -> $n       {...}      # `...` can infer from example list
  • 遍历区间, 不包含开始点和结束点
for my $i ( $start .. $limit ) { next if $i == $start or $i == $limit; ... }
for my $i ( ($start+1) .. ($limit-1) ) {...}
for ($start+1) .. ($limit-1) -> $i {...}
for $start    ^..^ $limit    -> $i {...}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容