Perl6Weekly(第二期)

:my $foo 的作用域和用途

regextokenrule 中, 定义像下面这样的变量是可能的:

token directive {
    :my $foo = "in command";
    <command> <subject> <value>?
}

在中提到了一点有关该变量的东西, 我引用过来:

任何 grammar regex 实际上是一种方法, 并且你可以在这样一个子例程中使用一个冒号跟着任何作用域声明符来声明一个变量, 这些声明符包括 my, our, stateconstant (作为类似的声明符, temp 和 let 也能被识别). 单个语句(直到结尾的分号或行末尾的闭括号为止) 被解析为普通的 Perl 6 代码:

token prove-nondeterministic-parsing {
    :my $threshold = rand;
    'maybe' \s+ <it($threshold)>
}

有谁能解释下这段代码的应用场景吗?

what scope does :my $foo; have?

:my $foo 在它所出现的 rule/token/regex 中拥有词法作用域(lexical scope)。你所得到的作用域要么很大要么很小:

grammar g {
    regex r1 {
        { my $foo; ...} # `$foo` 在该 block 的结尾超出作用域。
        ...
        { say $foo;   } # `$foo` 不在作用域中。
    }
}

grammar i {
    my $foo;
    regex r1   { ... } # 在 `r1` 内部, `$foo` 被识别出。
    ...
    regex r999 { ... } # 但是在 r999 中也是。
}

它的用途?

使用 :my $foo; 形式的变量声明以在 rule/token/regex 中声明本地作用域的变量, 如果没有进一步的声明, 那么这些变量能在 rule/token/regex 中的任何地方通过所声明的名字来引用。举个例子, 你可以看看 Rakudo 的 Grammar.nqp 源代码中的 token babble 中声明的 @extra_tweaks 变量的用法。

使用 :my $*foo; 形式的变量声明来声明动态的词法变量。动态变量能够, 在没有进一步声明的情况下, 在闭合词法作用域和闭合动态作用域中通过它们声明的名字来引用。作为说明, 请查看 the declaration of @*nibbles in Rakudo's Grammar moduleits use in Rakudo's Actions module

一般的使用场景

regular expressions 中一般不使用 :… 风格的声明。:...; 结构通常用在特别复杂和庞大的 grammars 中。对于这些使用场景, 依靠 Perl 6 的正则表达式和闭包的一致性是合适的。正是这使得 rule/token/regex 级别的 :...; 变量声明变得正当。

Regexes 和 closures 的一致性

很多 grammars 都是上下文有关的.

Perl 6 使 regexes 和 closures 统一了:

say Regex.^mro; (Regex) (Method) (Routine) (Block) (Code) ...

mro 是方法解析顺序, 这足以说明 regex 实际上是一种特殊类型的方法(就像方法是一种特殊类型的子例程一样)。

Perl6: is there a phaser that runs only when you fall out of a loop?

#!/usr/bin/env perl6

use v6.c;

ROLL:
for 1..10 -> $r {
    given (1..6).roll {
        when 6 {
            say "Roll $r: you win!";
            last ROLL;
        }
        default {
            say "Roll $r: sorry...";
        }
    }
    LAST {
        say "You either won or lost - this runs either way";
    }
}

更优雅的写法:

constant N = 5;
for flat (1..6).roll xx * Z 1..N -> $_, $n {
    print "roll $n: $_ ";

    when 6 {
        put "(won)";
        last;
    }

    default {
        put "(lost)";
    }

    LAST {
        print "result: ";
        when 6 { put "winner :)" }
        default { put "loser :(" }
    }
}

怎么从命令行传递一个复数给 sub MAIN?

#!/usr/bin/env perl6

use v6.c;

sub MAIN($x)
{
    say "$x squared is { $x*$x }";
}

我要在命令行中传递一个复数给 MAIN:

% ./square i
Cannot convert string to number: base-10 number must begin with valid digits or '.' in '⏏i' (indicated by ⏏)
  in sub MAIN at ./square line 7
  in block <unit> at ./square line 5

Actually thrown at:
  in sub MAIN at ./square line 7
  in block <unit> at ./square line 5

当我把脚本变为:

#!/usr/bin/env perl6

use v6.c;

sub MAIN(Complex $x)
{
    say "$x squared is { $x*$x }";
}

它竟然彻底罢工了:

% ./square i
Usage:
  square <x>

% ./square 1
Usage:
  square <x>

一种方法是使用 Coercive type declaration (强制类型声明), 从 Str 到 Complex:

sub MAIN(Complex(Str) $x) {
    say "$x 的平方为 { $x * $x }";
}

那么:

% ./squared.pl 1
1+0i 的平方为 1+0i
% ./squared.pl 1+2i
1+2i 的平方为 -3+4i

但是:

$ ./test.pl6 2
Usage:
  ./test.p6 <x> 

所以你真正需要的是把其它 Numeric 类型强转为 Complex 类型:

#!/usr/bin/env perl6

use v6.c;

sub MAIN ( Complex(Real) $x ) {
    say "$x squared is { $x*$x }";
}

我使用 Real 而非 Numeric, 因为 Complex 已经涵盖了其它的了。

Blessing a Hash into an object

为什么我写的这段代码不对呢?

class WordCount {
  has %!words; # Tried with both . and !
  method new($string) {
    my %words;
    my @sentence = split(/\s+/, $string);
    for @sentence -> $word {
      %words{$word}++;
    }
    return self.bless(:%words);
  }

  method sayCounts() {
    my @keys = keys(%!words);
    for @keys -> $key {
      say $key ~ " " ~ %!words{$key};
    }
  }
}

sub MAIN {
  my $sentence = "the boy jumped over the dog";
  my $wordCount = WordCount.new($sentence);
  $wordCount.sayCounts();
}

Perl6-ify:

use v6;

class WordCount {
  has Int %.words is default(0);

  method new($string) {
    my Int %words;
    for $string.split(/\s+/) -> $word {
      %words{$word}++;
    }

    self.bless(:%words)
  }

  method gist {
    %.words.map({.value ~ " " ~ .key}).join("\n")
  }
}

my $word-count = WordCount.new('the boy jumped over the dog');
say $word-count;

散列中的每一项都是一个 Pair:

my %w = a => 1;
%w.map({ say $_.^name }) # OUTPUT«Pair
»

所以:

%.words.map({.value ~ " " ~ .key}).join("\n")

等价于:

%.words.kv.map( -> $word, $count { "$word $count" } ).join("\n")

你还可以使用 sub-signature(子签名)来解构 .map 提供的 Pair

%.words.map( -> (:key($word), :value($count)) { "$word $count" } ).join("\n")
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容