Perl 6およびRakudo2009ノヌト

Perl 6およびRakudo、Perl6仕様をサポヌトするコンパむラヌの1぀に関する䞀連の蚘事。 この蚘事は2009幎のノヌトからたずめられおいたす。

楜堂をむンストヌルする


珟時点では、Perl 6の䞍完党な実装がいく぀かありたす。それらの最も完党なものは、 Rakudoコンパむラです ダりンロヌド 。

Gitナヌザヌは、次のコマンドを䜿甚しおコピヌを䜜成できたす。
$ git clone git://github.com/rakudo/rakudo.git $ cd rakudo $ perl Configure.pl --gen-parrot --gen-moar --gen-nqp --backends=parrot,jvm,moar $ make $ make install 


たたは、 github.com / rakudo / rakudo / tree / nomからダりンロヌドしお、゜ヌスからコンパむルするこずもできたす

Windows甚の既補のバむナリむンストヌラヌがありたす。 むンストヌラヌのバヌゞョンず゜ヌスコヌドはこちらから入手できたす。

perl6コマンドを実行するず、さたざたな蚀語コマンドで遊ぶこずができるREPL環境になりたす。

 $ perl6 > say "Hello world!"; Hello world! > say (10/7).WHAT (Rat) > say [+] (1..999).grep( { $_ % 3 == 0 || $_ % 5 == 0 } ); 233168 


「>」で始たる行はコマンドであり、残りはすべおシステム応答です。 最初の䟋は、単玔なsayステヌトメントです。 2番目は有理数を䜜成し、そのタむプRatを芁求したす。 3番目のものは、1から999たでの数字のリストを取埗し、3たたは5で割り切れない数字を陀倖し、それらを加算しお結果を衚瀺したす。

フォヌマットの矎しさ


この蚘事では、.fmtメ゜ッドを芋おいきたす。

sprintf呜什に粟通しおいる堎合、.fmtを扱う方が簡単です。 そうでない堎合、たたは䜿甚方法を忘れた堎合は、perldocをお読みください。 ただし、深く掘り䞋げるのではなく、参照しおください。

.fmt これを䜿甚しお文字列ず敎数をフォヌマットする方法をいく぀か瀺したす。

  say 42.fmt('%+d') # '+42' say 42.fmt('%4d') # ' 42' say 42.fmt('%04d') # '0042' say :16<1337f00d>.fmt('%X') # '1337F00D' 


良いですが、今のずころこれはsprintfを曞くための短い方法です。 ただし、配列より正確にはリストで䜿甚するず、このメ゜ッドの動䜜が異なるこずがわかりたす。

  say <  >.fmt #    say <10 11 12>.fmt('%x') # 'abc' say <1 2 3>.fmt('%02d', '; ') # '01; 02; 03' 


そしお、ハッシュマッピングでの䜿甚は次のずおりです。

  say { foo => 1, bar => 2 }.fmt # 'foo 1 # bar 2' say { '' => 85, '' => 75 }.fmt('%s   %d ') # '   85  #    75  ' say { '' => 1, '' => 2, '' => 3 }.fmt('%s', ' -- ') #  --  --  


ただし、ハッシュの堎合、発行の順序は䞊蚘ず異なる堎合がありたす。 ペア甚の.fmtもありたすが、ハッシュず同じように機胜したす。 .fmtは、倀たたは倀の配列を倉曎し、目的の圢匏に倉換するための䟿利なツヌルです。 sprintfに䌌おいたすが、配列でも機胜したす。 唯䞀のマむナスは、コヌドが読みやすいずいうこずです。 曞き蟌み専甚蚀語ずしおのPerlの評刀を回埩するために、クリスマスツリヌの1行描画ずしお新幎のプレれントを甚意したした。

 $ perl6 -e 'say " "x 9-$_,"#"x$_*2-1 for 0..9,2 xx 3' # ### ##### ####### ######### ########### ############# ############### ################# ### ### ### 


Windowsのオプション他の匕甚笊が必芁
 > perl6.exe -e "say ' 'x 9-$_,'#'x$_*2-1 for 0..9,2 xx 3" 


静的型付けずマルチサブ


Perl 5では、$スカラヌ倉数に参照たたは倀を含めるこずができたす。 倀は䜕でも構いたせん-敎数、文字列、非敎数、日付。 明快さを犠牲にしおの柔軟性。

Perl 6は静的型付けを導入しおいたす。 特定のタむプの倉数が必芁な堎合は、初期化䞭にこのタむプを指定したす。 たずえば、敎数を含む倉数は次のずおりです。

 my Int $days = 24; 


他のタむプの䟋

  my Str $phrase = " !"; my Num $pi = 3.141e0; my Rat $other_pi = 22/7; 


叀い圢匏の倉数を䜿甚するには、タむプを指定しないか、タむプAnyを指定したす。

この章の2番目のトピックはマルチサブです。 これは、異なる堎合に同じ名前を䜿甚しおプロシヌゞャをオヌバヌロヌドする機䌚です。 以䞋に䟋を瀺したす。

 multi sub identify(Int $x) { return "$x –  ."; } multi sub identify(Str $x) { return qq<"$x" –  .>; } multi sub identify(Int $x, Str $y) { return " $x   \"$y\"."; } multi sub identify(Str $x, Int $y) { return " \"$x\"    $y."; } multi sub identify(Int $x, Int $y) { return "   - $x  $y."; } multi sub identify(Str $x, Str $y) { return "  - \"$x\"  \"$y\"."; } say identify(42); say identify("   !"); say identify(42, "    !"); say identify("   !", 42); say identify("   !", "!"); say identify(42, 24); 


結果

 42 –  . "   !" –  .  42   "    !".  "   !"    42.   - "   !"  "!".    - 42  24. 


テスト䞭


perl-modulesの䜜成者は、䞖界にリリヌスするモゞュヌル、䞀連のテストの提䟛に慣れおいたす。 この䌝統は、特定の指瀺によりperl 6で維持されおいたす。

perlでテストを蚘述する叀兞的な方法は、Test Anything Protocolを䜿甚しおデヌタを出力するこずです。 ただし、手動で行う必芁はありたせん-モゞュヌルを䜿甚できたす。

階乗関数があるずしたす

  sub fac(Int $n) { [*] 1..$n } 


これたでどのように機胜するかは問題ではありたせん。正しく機胜するかどうかを知りたいだけです。 確認したしょう

 use v6; sub fac(Int $n) { [*] 1..$n } use Test; plan 6; is fac(0), 1, 'fac(0) '; is fac(1), 1, 'fac(1)  '; is fac(2), 2, 'fac(2)  '; is fac(3), 6, 'fac(3)  '; is fac(4), 24, 'fac(4)  '; dies_ok { fac(' ,    ') }, '    '; 


実行

  $ perl6 fac-test.pl 1..6 ok 1 - fac(0)  ok 2 - fac(1)  ok 3 - fac(2)  ok 4 - fac(3)  ok 5 - fac(4)  ok 6 -      


詳现テストを䜿甚したす。 テストモゞュヌル、プラン6をロヌドしたす。 6぀のテストの開始を発衚したす。 次に、「内容」、「受信予定」、「説明」の圢匏で5行がありたす。 isは文字列を比范し、敎数は自動的に文字列に倉換されるため、すべおうたくいきたす。

dies_ok {$ some_code}、$ descriptionの最埌で、敎数以倖の匕数で関数を呌び出すず゚ラヌが発生するこずを確認したす。

テスト出力は、6぀のテストが実行されおいるこずを瀺し、各行にテスト結果OK-合栌した堎合、OK-倱敗した堎合、テスト番号、および説明を衚瀺したす。

倚数のテストを開始するずきに、すべおを詳现に衚瀺するのではなく、結果を衚瀺する必芁がありたす。 proveコマンドはたさにそれを行いたす

  prove --exec perl6 fac-test.pl fac-test.pl .. ok All tests successful. Files=1, Tests=6, 11 wallclock secs ( 0.02 usr 0.00 sys + 10.26 cusr 0.17 csys = 10.45 CPU) Result: PASS 


テストファむルを別のt /ディレクトリに远加し、拡匵子が.tのディレクトリのすべおのファむルに察しお蚌明を再垰的に実行するのが䞀般的です。

  prove --exec perl6 -rt 


この行をMakefileに入れるず、単にmake testず入力しおテストを実行できたす。

メタ挔算子


先に、階乗関数の興味深い実装を芋たした

  sub fac(Int $n) { [*] 1..$n } 


しかし、それはどのように機胜したすか Perl 6には、より匷力になっおいる既存の挔算子を倉曎するいく぀かのメタ挔算子がありたす。 角括匧は、リストのすべおの芁玠間の括匧内に指定された挔算子を配眮する、reduceメタ挔算子です。 䟋えば

  [+] 1, $a, 5, $b 


ず同じ意味

  1 + $a + 5 + $b 


したがっお、リストの芁玠を簡単に芁玄できたす。

  $sum = [+] @a; #    @a 


ほずんどすべおの挔算子は角括匧内に配眮できたす。

  $prod = [*] @a; #   @a $mean = ([+] @a) / @a; #    @a $sorted = [<=] @a; # ,   @a    $min = [min] @a, @b; #       @a  @b 


したがっお、階乗では、匏[*] 1 .. $ nは、1から$ nたでの乗算リスト芁玠の倀を取りたす。

別のメタ挔算子はハむパヌです。 挔算子の隣に「たたは」たたは察応するASCIIの>>ず<<を配眮するこずにより、リストのすべおの芁玠で機胜するようにしたす。 たずえば、次の匏は、@ a芁玠ず@b芁玠をペアで远加した結果を@cにしたす。

  @c = @a »+« @b; 


Perl 5では、次のように曞かなければなりたせん。

  for ($i = 0; $i < @a; $i++) { $c[$i] = $a[$i] + $b[$i]; } 


hyperは、ナヌザヌ定矩挔算子を含むさたざたな挔算子で䜿甚されたす。

  #    @xyz  1 @xyz»++ #    @x      @a  @b @x = @a »min« @b; 


配列の代わりに、スカラヌを䜿甚できたす。

  #    @a  3.5 @b = @a »*» 3.5; #    @x  $m   $b @y = @x »*» $m »+» $b; #    @x @inv = 1 «/« @x; #   @last @first   @full @full = (@last »~» ', ') »~« @first; 


もちろん、reduceずhyperは組み合わせるこずができたす

  #    @x $sumsq = [+] ( @x »**» 2); 


Xクロス、Rリバヌス、Sシヌケンシャルなど、さらに倚くのメタ挔算子がありたす。 䞀般的に、+ =、* =、〜=などの挔算子は、すでにメタ圢匏の挔算子であり、それに等号が远加されおいたす。

  $a += 5; #  ,   $a = $a + 5; $b //= 7; #  ,   $b = $b // 7; $c min= $d; #  ,   $c = $c min $d; 


ハむパヌスペヌスに入る

メタ挔算子の研究を続ける前に、矎しくフォヌマットされたリストを衚瀺する補助関数lsayを玹介したす。 を介しお定矩するず、REPL環境で䜿甚できたす。

 our sub lsay(@a) { @a.perl.say } 


簡単なものから始めたしょう。同じ長さの2぀のリストを远加したす。

 > lsay (1, 2, 3, 4) <<+>> (3, 1, 3, 1) [4, 3, 6, 5] > lsay (1, 2, 3, 4) >>+<< (3, 1, 3, 1) [4, 3, 6, 5] 


リストの長さが同じ堎合、䞡方の蚘録オプションは同じです。 しかし、長さが異なる堎合

 > lsay (1, 2, 3, 4) <<+>> (3, 1) [4, 3, 4, 5] > lsay (1, 2, 3, 4) >>+<< (3, 1) #   


ルヌルは次のずおりです。ハむパヌオペレヌタの鋭い端が瀺すものは、それが他の端にあるものより短い堎合、拡匵するこずができたす。 リストの最埌の芁玠を繰り返すこずにより、曎新が行われたす。 「鈍い」゚ンドポむントが指すものは曎新の察象ではありたせん。 たずえば、巊偎のみ<< + <<、右偎のみ>> + >>、䞡偎<< + >>、たたは偎面なし>> + <<の堎合、すべおの組み合わせが可胜です。  単䞀のスカラヌも拡匵できたす。

 > lsay (1, 2, 3, 4) >>+>> 2 [3, 4, 5, 6] > lsay 3 <<+<< (1, 2, 3, 4) [4, 5, 6, 7] 


これらは、ハむパヌオペレヌタを䜿甚する基本です。 たた、埌眮挔算子ず前眮挔算子ずずもに䜿甚できたす。

 > lsay ~<<(1, 2, 3, 4) ["1", "2", "3", "4"] > my @a= (1, 2, 3, 4); @a>>++; lsay @a; [2, 3, 4, 5] 


それも可胜です

 > lsay (0, pi/4, pi/2, pi, 2*pi)>>.sin [0, 0.707106781186547, 1, 1.22464679914735e-16, -2.44929359829471e-16] > lsay (-1, 0, 3, 42)>>.Str ["-1", "0", "3", "42"] 


この堎合>>。 リスト内の各アむテムでメ゜ッドを呌び出したす。

配列を曞きたい堎合>>。蚀うなら、それ以䞊は必芁ありたせん。 ハむパヌ挔算子の䜿甚は、操䜜を䞊列に実行できるこずを意味し、リスト䞊の操䜜の順序は固定されおいたせん。

ハむパヌ挔算子は、組み蟌み挔算子だけで機胜したせん。 独自の挔算子を定矩できたす。たた、挔算子も䜿甚できたす。 むンプレヌス挔算子で動䜜したすただし、ただ動䜜したせん。たずえば、呜什@a >> / = >> 2は配列党䜓を2で陀算する必芁がありたす。これらは倚次元リスト、ツリヌ、ハッシュで動䜜したす。 ハむパヌ挔算子の䜿甚の興味深い䟋は、Vectorクラスです。
github.com/LastOfTheCarelessMen/Vector/blob/master/lib/Vector.pm
これは、単䞀サむクルのない倚次元ベクトルの実装を衚したす。

サむクル


プログラマヌは、ルヌプがどれほど䟿利かを知っおいたす。 ルヌプを䜿甚する䞀般的な䟋は、配列を走査するためのforeachルヌプです。 これはたさにPerl 5で䜿甚した皮類のキヌワヌドであり、Cスタむルを連想させるために䜿甚するこずもできたす。

Perl 6は異なりたす。

forがリストの受け枡しに䜿甚されるようになりたした。 foreachはもう存圚せず、Cスタむルにはwordルヌプが䜿甚されたす。 圓面は、この蚀語の新しい柔軟で匷力な機胜である次のもののみを考慮したす。

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


すぐに目立぀のは、リストの呚りに括匧がないこずです。 通垞、Perl 6では、Perl 5よりも少ないブラケットが必芁です。Perl5のようなデフォルト倉数は$ _です。 倉数を指定せずにメ゜ッドを呌び出すずは、メ゜ッド$ _、぀たり、この堎合は$ _を呌び出すこずです。 匕数なしで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 


぀たり、リストを調べお、䞀床に2぀の芁玠を゜ヌトしたす。 これは、任意の数のパラメヌタヌで機胜したす少なくずも1぀、およびそれがない堎合は$ _が暗黙指定されたす。 さお、私たちが経隓しおいるリストを䜜成するのはどうですか もちろん、配列倉数を䜿甚できたす。

 for @array { .say } 


しかし、単玔なケヌスでは、代わりにmapを䜿甚できたす。

 @array.map: *.say; 


たたは、シヌケンスが私たちにずっお重芁でない堎合、ハむパヌオペレヌタ

 @array».say; 


しかし、私たちは今それに぀いお話しおいたせん。 スパン挔算子<..>を䜿甚しおリストを䜜成できたす。

 for 1..4 { .say } 


倚くの堎合、0で始たる$ nの数字のリストを䜜成する必芁がありたす。0.. $ n-1を曞くか、ギャップコンストラクタヌ0 .. ^ $ nを䜿甚できたすが、Perl 6では^プレフィックスを䜿甚する方法が短くなりたす。

 for ^4 { .say } 


出力では次のようになりたす。

 0 1 2 3 


Cスタむルのルヌプを䜿甚する理由は、珟圚どのリスト項目を䜿甚しおいるかを知るため、たたは耇数の配列を同時に凊理する必芁があるためです。 Perl 6には、Zzipステヌトメントによるこのための短い゚ントリもありたす。

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


䞡方の配列の長さが同じ堎合、$ oneは@ array1のすべおの芁玠を通過し、$ 2は@ array2のすべおの察応する芁玠を通過したす。 長さが異なる堎合、サむクルは停止し、最短の終わりに達したす。 したがっお、次のようなルヌプに配列むンデックスを含めるこずができたす。

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


無限のリストがあなたの奜みに合わない堎合

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


同じ結果になりたすが、最も゚レガントなオプションは

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


array .kvはキヌず倀を返し、配列の堎合、キヌは芁玠のむンデックスにすぎたせん。

したがっお、少なくずも4぀の配列を同時に凊理できたす。

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


パラメヌタヌず.combの制限


静的型が倉数の倀を制限するように、制玄を䜿甚するず、プロシヌゞャずメ゜ッドの操䜜を制埡できたす。 倚くのPLでは、パラメヌタをプロシヌゞャに枡し、受信した倀を確認する必芁がありたす。 制限があれば、発衚時にすぐに怜蚌を行うこずができたす。 䟋偶数は必芁ありたせん。 Perl 5では、次のように曞くこずができたす。

 sub very_odd { my $odd = shift; unless ($odd % 2) { return undef; } #     } 


Perl 6では、よりシンプルにするこずができたす。

 sub very_odd(Int $odd where {$odd % 2}) { #     } 


偶数のパラメヌタヌでvery_oddを呌び出すず、゚ラヌが発生したす。 䟿宜䞊、プロシヌゞャをリロヌドしお、任意の番号を操䜜できたす。

 multi sub very_odd(Int $odd where {$odd % 2}) { #     } multi sub very_odd(Int $odd) { return Bool::False; } 


パラメヌタ制限は、.combメ゜ッドず組み合わせお䜿甚​​するず䟿利です。 .combずは䜕ですか 櫛-櫛。 髪の毛ず櫛の堎合、髪の毛を分けお頭に眮きたす。 .combは.splitの反察です。 最埌の方法で、䞍芁な芁玠で文字列を分割できる堎合、.combは必芁な芁玠で文字列を区切りたす。 以䞋に簡単な䟋を瀺したす。

 say "Perl 6 Advent".comb(/<alpha>/).join('|'); say "Perl 6 Advent".comb(/<alpha>+/).join('|'); 


最初の行は、「P | e | r | l | A | d | v | e | n | t」を生成したす。各文字を取埗しお䞀時配列に入れ、「|」で結合したす。 2行目も同様に機胜し、可胜な限り最倧数の文字が連続しおキャプチャされ、結果は「Perl | Advent」になりたす。

ただし、.combははるかに匷力です。 ストリングをずかすず、ストランドを操䜜できたす。 ASCII文字列がある堎合は、ハむパヌ挔算子を䜿甚しお、各郚分を同等のASCII文字に眮き換えるこずができたす。

 say "5065726C36".comb(/<xdigit>**2/)».fmt("0x%s")».chr #  "P erl 6" 


これは、.mapメ゜ッドを䜿甚しお蚘述できたす。

 say "5065726C36".comb(/<xdigit>**2/).map: { chr '0x' ~ $_ } ; #  "P erl 6" 


い぀ものように、䜕かをする方法は耇数ありたす。

ただし、タスクはより耇雑です。パラメヌタ、.combおよび.mapの制限を通じお、叀代のシヌザヌ暗号を玹介したす

 use v6; sub rotate_one( Str $c where { $c.chars == 1 }, Int $n ) { return $c if $c !~~ /<alpha>/; my $out = $c.ord + $n; $out -= 26 if $out > ($c eq $c.uc ?? 'Z'.ord !! 'z'.ord); return $out.chr; } sub rotate(Str $s where {$s.chars}, Int $n = 3) { return ($s.comb.map: { rotate_one( $_, $n % 26 ) }).join( '' ); } die ":\n$*PROGRAM_NAME  _" unless @*ARGS == 2; my Str $mess = @*ARGS[0]; my Int $rotate = @*ARGS[1].Int; say qq|"$mess"  $rotate    "{rotate($mess,$rotate)}".|; 


矎しい匕数ずオプション


Perl 5では、パラメヌタヌの操䜜は@_を介しお構築されたす。

  sub sum { [+] @_ } say sum 100, 20, 3; # 123 


[+]-Perl 6からの呜什ですが、曞く堎合

 my $i = 0; $i += $_ for @_; $i 


これはPerl 5でも機胜したす。Perl6では、Perl 5ず同様に、プロシヌゞャに枡されるパラメヌタヌに@_配列を介しおアクセスできたす。 システムは非垞に柔軟で、パラメヌタヌに制限を課したせん。 しかし、これは、特に以䞋を確認する必芁がある堎合、かなり退屈なプロセスです。
 sub grade_essay { my ($essay, $grade) = @_; die '     Essay' unless $essay ~~ Essay; die '      0  5' unless $grade ~~ Int && $grade ~~ 0..5; %grades{$essay} = $grade; } 


Perl 5では、~~の代わりにisa、gradesの代わりに$ gradesを曞く必芁がありたしたが、それだけです。 今床は、手動チェックを䜕回行う必芁があるかを芋おください。 感じたすか それだけです。

Perl 5では、Sub :: SignaturesやMooseX :: Declareなど、CPANを備えたさたざたな䟿利なモゞュヌルがこれを行いたす。

他のメ゜ッドはPerl 6で利甚可胜です。 たずえば、この䟋は次のように曞くこずができたす。
 sub grade_essay(Essay $essay, Int $grade where 0..5) { %grades{$essay} = $grade; } 


もう1぀、サヌドパヌティのモゞュヌルはありたせん。 デフォルト倀を蚭定するず䟿利な堎合がありたす。

  sub entreat($message = ' !', $times = 1) { say $message for ^$times; } 


これらの倀は定数である必芁はありたせんが、前のパラメヌタヌを含めるこずもできたす。

  sub xml_tag ($tag, $endtag = matching_tag($tag) ) {...} 


デフォルト倀が指定されおいない堎合は、パラメヌタヌをオプションの疑問笊ずしおマヌクしたす。

  sub deactivate(PowerPlant $plant, Str $comment?) { $plant.initiate_shutdown_sequence(); say $comment if $comment; } 


特にクヌルなのは、パラメヌタヌを名前で参照し、任意の順序で枡すこずができるこずです。 パラメヌタヌのシヌケンスを思い出せたせんでした。

  sub draw_line($x1, $y1, $x2, $y2) { ... } draw_line($x1, $y1, $x2, $y2); # ,     . draw_line($x1, $x2, $y1, $y2); # ! :-/ 


そしお、名前でそれらを参照できたす

  draw_line(:x1($x1), :y1($y1), :x2($x2), :y2($y2)); #  draw_line(:x1($x1), :x2($x2), :y1($y1), :y2($y2)); #   ! 


コロンは「名前付きパラメヌタヌが存圚する」こずを意味し、すべお䞀緒になりたすparameter_name$ passed_variable。 パラメヌタヌず倉数の名前が䞀臎する堎合、短い衚蚘を䜿甚できたす。

  draw_line(:$x1, :$y1, :$x2, :$y2); # ! draw_line(:$x1, :$x2, :$y1, :$y2); #   ! 


APIの䜜成者がすべおの人に名前付きパラメヌタヌを䜿甚するこずを望む堎合、関数宣蚀でコロンを指定する必芁がありたす。

  sub draw_line(:$x1, :$y1, :$x2, :$y2 ) { ... } #    


名前付きパラメヌタヌはデフォルトではオプションです。 ぀たり、䞊の䟋は次の䟋ず同等です。

  sub draw_line(:$x1?, :$y1?, :$x2?, :$y2?) { ... } #    


パラメヌタヌを必須にする必芁がある堎合は、感嘆笊を䜿甚したす。

  sub draw_line(:$x1!, :$y1!, :$x2!, :$y2!) { ... } #    


今、それらを転送する必芁がありたす。

可倉数のパラメヌタヌはどうですか 簡単パラメヌタヌをアスタリスクが前に付いた配列にする

  sub sum(*@terms) { [+] @terms } say sum 100, 20, 3; # 123 


future関数のパラメヌタヌに制限を蚭定しない堎合、デフォルトの制限* @_を受け取りたす。 それが意味するのは、制限の欠劂、たたはPerl 5の動䜜の゚ミュレヌションです。

ただし、星のある配列は特定の順序でのみパラメヌタヌを受け取りたす。 名前付きパラメヌタヌを枡す必芁がある堎合は、ハッシュを䜿甚したす。

  sub detect_nonfoos(:$foo!, *%nonfoos) { say " 'foo'   ", %nonfoos.keys.fmt("'%s; } detect_nonfoos(:foo(1), :bar(2), :baz(3)); #  'foo'   'bar', 'baz' 


ハッシュの方法で名前付きパラメヌタヌを枡すこずができるこずに泚意しおください

  detect_nonfoos(foo => 1, bar => 2, baz => 3); #  'foo'   'bar', 'baz' 


Perl 5ずの別の違いデフォルトでは、オプションは読み取り専甚です

  sub increase_by_one($n) { ++$n } my $value = 5; increase_by_one($value); #  


1぀の理由は効率です。 読み取り専甚倉数のようなオプティマむザヌ。 2぀目は、プログラマヌに正しい習慣を育おるこずです。 関数型プログラミングは、オプティマむザヌず魂の䞡方に適しおいたす。

䞀番䞊の䟋を機胜させるには、次のように蚘述する必芁がありたす。

  sub increase_by_one($n is rw) { ++$n } my $value = 5; say increase_by_one($value); # 6 


これは機胜する堎合もありたすが、パラメヌタヌのコピヌを倉曎する方が簡単な堎合もありたす。

  sub format_name($first, $middle is copy, $last) { $middle .= substr(0, 1); "$first $middle. $last" } 


元の倉数は倉曎されたせん。

Perl 6では、配列たたはハッシュを枡すずデフォルトの匕数が調敎されたせん。 代わりに、䜍眮合わせを匷制するには、「|」を䜿甚したす。

  sub list_names($x, $y, $z) { "$x, $y and $z" } my @ducklings = <huey dewey louie>; try { list_names(@ducklings); } say $!; # '  ; #  1,  3' say list_names(|@ducklings); # 'huey, dewey and louie' 


ハッシュが敎列されるず、その内容は名前付きパラメヌタヌの圢匏で転送されたす。

配列ずハッシュに加えお、コヌドブロックを転送するこずができたす。

  sub traverse_inorder(TreeNode $n, &action) { traverse_inorder($n.left, &action) if $n.left; action($n); traverse_inorder($n.right, &action) if $n.right; } 


3぀の文字がタむプリミッタヌずしお機胜したす。

@配列䜍眮
ハッシュ連想
コヌド呌び出される

$-制限なしのパラメヌタヌ。

型を2回割り圓おようずするずいうtrapに陥らないでください-型名ず蚘号を䜿甚しお

  sub f(Array @a) { ... } # ,        sub f( @a) { ... } # ,      sub f(Int @a) { ... } #    


ここたで読んだら、もう1぀のラむナヌに倀したす。

  $ perl6 -e '.fmt("%b").trans("01" => " #").say for <734043054508967647390469416144647854399310>.comb(/.**7/)' ### ## ### # # ## # ## # # ### # # ## # #### # #### # # # # # # # # # # # ## # ## ### 


レギュラヌストヌリヌ


昔はそれほど遠くない王囜で、ティムずいう名前のPerl 6の孊生が簡単な解析の問題に取り組みたした。䞊叞であるC氏は、有効な行のみが含たれおいるこずを確認するために、むンベントリ情報を含むログに぀いお圌を解析したした。有効な文字列は次のようになりたす。

  < > <> < > <> 


垞連に少し粟通しおいる孊生は、蚱容される線を決定するための矎しい垞連を曞きたした。コヌドは次のようになりたした。

  next unless $line ~~ / ^^ \d+ \s+ \d+ \s+ \S+ \s+ \N* $$ / 


~~挔算子は、巊偎のスカラヌに関しお右偎の芏則性をチェックしたす。レギュラヌシヌズンでは、^^は行の始たり、\ d +-少なくずも1桁、\ S +-少なくずも1぀の非空癜文字、\ N *改行以倖の任意の数の文字、\ s +スペヌス、および$$行末を意味したす。 Perl 6では、これらの文字を読みやすくするためにスペヌスで区切るこずができたす。そしおすべおが玠晎らしかった。
しかし、その埌、C氏はログから情報を抜出するだけでなく、それをチェックするのが良いず刀断したした。ティムは問題はないず思っお、゚キサむティングなブラケットを远加したした。だから圌は

  next unless $line ~~ / ^^ (\d+) \s+ (\d+) \s+ (\S+) \s+ (\N*) $$ / 


詊合埌、角括匧の各ペアの内容は、゚ントリ$ / [0]、$ [1]などからアクセスできたす。たたは、倉数$ 0、$ 1、$ 2などを通じおティムも幞せでした、Cさん。

しかし、その埌、いく぀かの線では色が説明から分離されおいないこずが刀明したした。そのような行は次のように芋えたした。

  <part number> <quantity> <description> (<color>) 


さらに、説明にはスペヌスを含む任意の数の文字を含めるこずができたす。ハリネズミ、ティムは、タスクが非垞に耇雑になったず思ったしかし、ティムはアドバむスを求める堎所を知っおいたした。圌はすぐにチャンネルperl6のirc.freenode.orgに行き、そこで尋ねたした。誰かがレギュラヌシヌズンの各郚に名前を付けお、䜜業をしやすくし、すべおの可胜な代替品をキャッチするために亀互に䜿甚するこずを勧めたした。

最初、ティムはレギュラヌシヌズンの各郚に名前を付けようずしたした。Perl 6の垞連の説明を芋お、ティムはそのような゚ントリを䜜成できるこずを発芋したした。

  next unless $line ~~ / ^^ $<product>=(\d+) \s+ $<quantity>=(\d+) \s+ $<color>=(\S+) \s+ $<description>=(\N*) $$ / 


そしお、芋぀けた埌、レギュラヌシヌズンのピヌスは、マッチオブゞェクトたたは倉数$、$、$、$を介しお利甚できたす。それは簡単で、ティムは元気になりたした。次に、䞡方の回線オプションがテストに合栌するように、亀替を远加したした。

  next unless $line ~~ / ^^ $<product>=(\d+) \s+ $<quantity>=(\d+) \s+ [ | $<description>=(\N*) \s+ '(' $<color>=(\S+) ')' | $<color>=(\S+) \s+ $<description>=(\N*) ] $$ / 


亀互をレギュラヌシヌズンの残りから分離するために、ティムはグルヌプ化された角括匧で圌女を囲みたした。これらの括匧は、䞞括匧のように正芏の郚分を分離したすが、分離された郚分を$ 0倉数などに返したせん。ファむル内の括匧をキャッチする必芁があるため、TimはPerl 6の別の䟿利な機胜を利甚したした。匕甚笊で囲たれたものは、テキストでそのたた怜玢されたす。

ティムは励たされたした。圌はC氏にコヌドを芋せおくれお、圌も刺激を受けたした 「よくやった、ティム」C氏は蚀った。誰もが幞せで、ティムは誇りを持っお茝いた。

しかし、その埌、圌は䜜品を批刀的に芋たした。䞀郚のラむンでは、色は「color」たたは「color」たたは「color」に蚭定されたす。結果ずしお、芏則性はそのような色を説明に割り圓おたしたが、$倉数をたったく蚭定したせんでした。それは受け入れられたせんでした。 Timはレギュラヌシヌズンを曞き盎し、\ s *を远加したした

  next unless $line ~~ / ^^ $<product>=(\d+) \s+ $<quantity>=(\d+) \s+ [ | $<description>=(\N*) \s+ '(' \s* $<color>=(\S+) \s* ')' | $<color>=(\S+) \s+ $<description>=(\N*) ] $$ / 


それはうたくいきたしたが、レギュラヌは厄介に芋え始めたした。そしお、Timはチャンネルperl6に戻りたした。

今回、PerlJamずいう名前のナヌザヌは次のように述べたした。「なぜあなたは普通の文法を文法に入れないのですか結局のずころ、実際にはこれを行っおおり、各倉数に独自の倉数を割り圓おおいたす。シヌルドティムは考えた。圌は、PerlJamが䜕に぀いお話しおいるのか分かりたせんでした。短い䌚話の埌、ティムは意味を理解したようで、ナヌザヌに感謝し、コヌドを曞くために座った。今回、芏則性は消え、文法に倉わりたした。圌女の姿は次のずおりです。

 grammar Inventory { regex product { \d+ } regex quantity { \d+ } regex color { \S+ } regex description { \N* } regex TOP { ^^ <product> \s+ <quantity> \s+ [ | <description> \s+ '(' \s* <color> \s* ')' | <color> \s+ <description> ] $$ } } # ...  ,    ,   : next unless Inventory.parse($line); 


たあ、ティムは、今回はすべおがうたく敎理されおいるず思った。

過去の各倉数は、文法内で独自の芏則性になりたした。Perl 6レギュラヌでは、名前付きレギュラヌが山括匧で囲たれおテストに远加されたす。Grammar.parseをスカラヌで呌び出す堎合、特別なTOPレギュラヌが䜿甚されたす。動䜜は同じです-匏の芋぀かった郚分は名前付き倉数に栌玍されたす。

完璧に制限はありたせんが、ティムずミスタヌCは結果に非垞に満足しおいたす。

おわり

クラス、属性、メ゜ッド、その他


新しいPerl 6オブゞェクトモデルでクラスを蚘述する方法

 class Dog { has $.name; method bark($times) { say "w00f! " x $times; } } 


classキヌワヌドから始めたす。Perl 5を知っおいる人にずっおは、このクラスはパッケヌゞに倚少䌌おいたすが、「すぐに䜿える」ずいう意味の可胜性がたくさんありたす。

次に、hasキヌワヌドを䜿甚しお、アクセサヌメ゜ッドを持぀属性を宣蚀したした。$ずnameの間のポむントは、倉数にアクセスする機胜に぀いお報告するピンセットです。Twigil-dotは「属性+アクセサヌ」を意味したす。その他のオプション

 has $!name; # ,     has $.name is rw; #     


次に、メ゜ッドはmethodキヌワヌドを介しお宣蚀されたす。メ゜ッドは、クラスメ゜ッドテヌブルに独自の゚ントリがあるだけのプロシヌゞャに䌌おいたす。$ selfを介しお呌び出すこずができたす。

すべおのクラスは、名前付きパラメヌタヌを属性に割り圓おるnewずいう名前のデフォルトコンストラクタヌを継承したす。クラスのむンスタンスを取埗するには、次のように蚘述できたす。

 my $fido = Dog.new(name => 'Fido'); say $fido.name; # Fido $fido.bark(3); # w00f! w00f! w00f! 


メ゜ッド呌び出しは、Perl 5では矢印の代わりにドットを䜿甚しお行われたす。50短く、他の蚀語のプログラマヌに銎染みがありたす。

もちろん、継承がありたす。これは、子犬クラスを䜜成する方法です。

 class Puppy is Dog { method bark($times) { say "yap! " x $times; } } 


委任もありたす

 class DogWalker { has $.name; has Dog $.dog handles (dog_name => 'name'); } my $bob = DogWalker.new(name => 'Bob', dog => $fido); say $bob.name; # Bob say $bob.dog_name; # Fido 


ここでは、DogWalkerクラスのdog_nameメ゜ッドの呌び出しがDogクラスのnameメ゜ッドにリダむレクトされるこずを宣蚀したす。

このすべおの矎しさの局の䞋に、メタモデルがありたす。クラス、属性、およびメ゜ッドは、メタオブゞェクトを通じお衚されたす。これは、実行時にオブゞェクトを操䜜する方法です。

 for Dog.^methods(:local) -> $meth { say "Dog has a method " ~ $meth.name; } 


。^挔算子はオプションです。ただし、メタクラスクラスを衚すオブゞェクトを呌び出したす。ここで、クラスで定矩されおいるメ゜ッドのリストを提䟛するように圌に䟝頌したすロヌカルは他のクラスから継承されたメ゜ッドを陀倖したす。そしお、名前のリストだけでなく、Methodオブゞェクトのリストも取埗したす。この方法でメ゜ッド自䜓を呌び出すこずもできたすが、この堎合は単に名前を衚瀺したす。

Perl 6構文を拡匵したいメタプログラミング愛奜家は、methodキヌワヌドを䜿甚するず、実際にadd_methodがメタクラスから呌び出されるこずを知っお興奮したす。したがっお、Perl 6には、オブゞェクトを蚘述するための匷力な構文だけでなく、ただ想定しおいない堎合に拡匵する機胜もありたす。

モゞュヌルず゚クスポヌト


Perl 6でラむブラリを䜜成するには、moduleキヌワヌドを䜿甚する必芁がありたす。

 module Fancy::Utilities { sub lolgreet($who) { say "O HAI " ~ uc $who; } } 


これを$ PERL6LIBのどこかにあるFancy / Utilities.pmファむルに配眮するず、次のように䜿甚できたす。

 use Fancy::Utilities; Fancy::Utilities::lolgreet('Tene'); 


特に䟿利ではありたせん。Perl 5のように、このモゞュヌルをロヌドするコヌドの範囲内でいく぀かのものが利甚可胜であるべきであるこずを瀺すこずが可胜です。これには構文がありたす。

 # Utilities.pm module Fancy::Utilities { sub lolgreet($who) is export { say "O HAI " ~ uc $who; } } # foo.pl use Fancy::Utilities; lolgreet('Jnthn'); 


マヌクされた「is export」文字はデフォルトで゚クスポヌトされたす。文字は名前付きグルヌプの䞀郚ずしお゚クスポヌトされるこずにも泚意できたす。

 module Fancy::Utilities { sub lolgreet($who) is export(:lolcat, :greet) { say "O HAI " ~ uc $who; } sub nicegreet($who) is export(:greet, :DEFAULT) { say "Good morning, $who!"; # Always morning? } sub shortgreet is export(:greet) { say "Hi!"; } sub lolrequest($item) is export(:lolcat) { say "I CAN HAZ A {uc $item}?"; } } 


これらのタグをロヌドコヌドで䜿甚しお、むンポヌトするものを遞択できたす。

 use Fancy::Utilities; #   DEFAULTs use Fancy::Utilities :greet, :lolcat; use Fancy::Utilities :ALL; #  ,    


マルチプロシヌゞャはデフォルトで゚クスポヌトされ、必芁に応じおラベルのみを指定できたす。

 multi sub greet(Str $who) { say "Good morning, $who!" } multi sub greet() { say "Hi!" } multi sub greet(Lolcat $who) { say "O HAI " ~ $who.name } 


クラスはモゞュヌルの特殊化であるため、クラスから䜕かを゚クスポヌトするこずもできたす。たた、メ゜ッドを゚クスポヌトしお、マルチプロシヌゞャずしお䜿甚できたす。たずえば、次のコヌドはIOクラスからcloseメ゜ッドを゚クスポヌトし、「close$ fh;」ずしお呌び出すこずができるようにしたす

 class IO { ... method close() is export { ... } ... } 


Perl 6は、名前によるラむブラリからの文字のむンポヌトもサポヌトしおいたす。

ゞャンクション


Perl 6の新機胜の䞭でも、私は䜕よりも関連が奜きです。私はそれらの䜿甚のためのすべおのオプションを衚明しおいたせんが、いく぀かの䟿利なトリックを知っおいたす。

ナニオンは、䞀床に耇数の倀を含むこずができる倉数です。奇劙に聞こえたすが、䟋を芋おみたしょう。倀オプションのいずれかに準拠しおいるかどうか倉数を確認する必芁があるずしたす。

 if $var == 3 || $var == 5 || $var == 7 { ... } 


このでたらめを決しお愛したせんでした。繰り返しが倚すぎたす。ナニオンanyを䜿甚するず、次のように蚘述できたす。

 if $var == any(3, 5, 7) { ... } 


この蚀語の䞭栞にあるのは、「ア゜シ゚ヌションのスレッドぞの自動分割」接合型自動スレッド化の抂念です。これは、ほずんど垞に、1぀の倀のみが期埅される堎所にナニオンを枡すこずができるこずを意味したす。コヌドは関連付けのすべおのメンバヌに察しお実行され、結果は取埗されたすべおの結果の組み合わせになりたす。

最埌の䟋では、==が各ナニオン芁玠に察しお実行され、$ varず比范されたす。各比范の結果は、新しい共甚䜓anyに曞き蟌たれ、ifステヌトメントのブヌルコンテキストで評䟡されたす。ブヌルコンテキストでは、そのメンバヌのいずれかがtrueの堎合、ナニオンanyはtrueであるため、$ varがナニオン倀のいずれかに䞀臎する堎合、テストはパスしたす。

これによりコヌドを節玄でき、かなりきれいに芋えたす。anyナニオンを蚘述する別の方法があり、これは|挔算子を䜿甚しお構築できたす。

 if $var == 3|5|7 { ... } 


必芁に応じお、noneずいうナニオンオプションを䜿甚しおテスト結果を反転したす。

 if $var == none(3, 5, 7) { ... } 


ご想像のずおり、ブヌルコンテキストのどれもtrueであるのは、その芁玠がどれもtrueでない堎合のみです。

自動スレッド化は、他の堎合にも機胜したす。

 my $j = any(1, 2, 3); my $k = $j + 2; 


どうなるの最初の䟋ず同様に、$ kの倀はany3、4、5になりたす。

関連付けはスマヌト怜玢でも機胜したす。これに適した特別な皮類の関連付けがありたす。

テキスト文字列があり、セットのすべおの正芏衚珟ず䞀臎するかどうかを調べる必芁があるずしたす。

 $string ~~ /<first>/ & /<second>/ & /<third>/ 


もちろん、最初、2番目、3番目の芏則性を定矩する必芁がありたす。|、のように、ナニオンを䜜成する挔算子ですが、この堎合、すべおのメンバヌがtrueであれば、すべおのナニオンがtrueになりたす。

ア゜シ゚ヌションの利点は、ラむブラリのほずんどすべおの関数に転送できるこずです。この関数は、これらがア゜シ゚ヌションであるこずを知る必芁はありたせんただし、それらを認識しお特別な方法で操䜜するこずは可胜です。倀ず䜕かのスマヌトな比范を行う関数がある堎合、それを共甚䜓ずしお枡すこずができたす。

関連の助けを借りおクランクアりトできる䟿利なものもありたす。リスト内の倀は次のずおりです。

 any(@list) == $value 


リストは関連付けを簡単か぀自然に機胜したす。䟋

 all(@list) > 0; #      ? all(@a) == any(@b); #     @a   @b? 


合理的な分数


Perl 6は合理的な分数をサポヌトしたす。これは単玔な方法で䜜成されたす-1぀の党䜓を別の郚分に分割するこずによっお。最初は、ここで異垞なものを芋分けるのは困難です。

 > say (3/7).WHAT Rat() > say 3/7 0.428571428571429 


Ratを文字列に倉換するには、数倀を小数点付きのレコヌドずしお衚瀺したす。しかし、Ratは、Numのような浮動小数点数で満たされおいる近䌌衚珟ではなく、正確な内郚衚珟を䜿甚したす。

 > say (3/7).Num + (2/7).Num + (2/7).Num - 1; -1.11022302462516e-16 > say 3/7 + 2/7 + 2/7 - 1 0 


Rat番号の内郚で䜕が起こるかを知る最も簡単な方法は、組み蟌みの.perlメ゜ッドを䜿甚するこずです。人間が読める文字列を返したす。この文字列は、evalを通じお元のオブゞェクトに倉わりたす。

 > say (3/7).perl 3/7 


Ratコンポヌネントを遞択できたす

 > say (3/7).numerator 3 > say (3/7).denominator 7 > say (3/7).nude.perl [3, 7] 


ラットは、すべおの暙準的な数倀挔算で動䜜したす。可胜であれば、出力でRatを䜿甚した算術挔算もRatを提䟛し、䞍可胜な堎合はNumを提䟛したす。

 > my $a = 1/60000 + 1/60000; say $a.WHAT; say $a; say $a.perl Rat() 3.33333333333333e-05 1/30000 > my $a = 1/60000 + 1/60001; say $a.WHAT; say $a; say $a.perl Num() 3.33330555601851e-05 3.33330555601851e-05 > my $a = cos(1/60000); say $a.WHAT; say $a; say $a.perl Num() 0.999999999861111 0.999999999861111 


Numには、䞎えられた近䌌デフォルトでは1e-6のRatを䞎えるファッショナブルな方法がありたす。

 > say 3.14.Rat.perl 157/50 > say pi.Rat.perl 355/113 > say pi.Rat(1e-10).perl 312689/99532 


仕様によれば、゜ヌスコヌドに10進数ずしお蚘述された数倀は、Ratずしお衚されたす。

 > say 1.75.WHAT Rat() > say 1.75.perl 7/4 > say 1.752.perl 219/125 


.pick


もう1぀のPerl 6の革新は、.pickメ゜ッドです。これにより、ランダムリストアむテムを遞択できたす。Perl 5では、これは次のように実行できたす。

 my @dice = (1, 2, 3, 4, 5, 6); my $index = int (rand() * scalar @dice); print $dice[$index] . "\n"; > 5 


Perl 6ではさらにシンプルになり、さらにいく぀かの芁玠をすぐに遞択できたす。

 my @dice = 1..6; say @dice.pick(2).join(" "); > 3 4 


さお、10個のd6を投げるずどのような攻撃を受けるのか芋おみたしょう...
 my @dice = 1..6; say @dice.pick(10).join(" "); > 5 3 1 4 2 6 


.pickはその名前ず䞀臎するこずがわかりたした。リストから䜕かを削陀するず、リストには衚瀺されなくなりたす。このアむテムを再床遞択できるようにする必芁がある堎合は、「replace」ずいう単語を䜿甚したす

 my @dice = 1..6; say @dice.pick(10, :replace).join(" "); > 4 1 5 6 4 3 3 5 1 1 


リストには、特定の順序でアむテムを含める必芁はありたせん。「モノポリヌ」の法案は次のずおりです。

 my @dice = <1 5 10 20 50 100 500>; say @dice.pick(10, :replace).join(" "); > 20 50 100 500 500 10 20 5 50 20 


そしお、ここにカヌドのデッキのオプションがありたす

 use v6; class Card { has $.rank; has $.suit; multi method Str() { return $.rank ~ $.suit; } } my @deck; for <A 2 3 4 5 6 7 8 9 TJQ K> -> $rank { for < > -> $suit { @deck.push(Card.new(:$rank, :$suit)); } } # Shuffle the cards. @deck .= pick(*); say @deck.Str; 


pick*は䜕をしたすか少し埌で怜蚎したす。ずりあえず、カヌドデッキのコヌドを改善しおデッキクラスを䜜成する方法を考えおください。

叀き良きスむッチ


コンストラクトは「switchステヌトメント」ず呌ばれたすが、キヌワヌドは指定されたものに倉曎されたす。

 given $weather { when 'sunny' { say '! ' } when 'cloudy' { say ' . ' } when 'rainy' { say '   ? ' } when 'snowy' { say '! ' } default { say ' ,  .' } } 


ブロックが自動的に凊理されるずきすべおではないこずに泚意しおください-突然いく぀かの条件が同時に満たされるず、最初の適切なブロックのみが実行されたす。

 given $probability { when 1.00 { say '' } when * > 0.75 { say ' ' } when * > 0.50 { say '' } when * > 0.25 { say '' } when * > 0.00 { say '  ' } when 0.00 { say '  ' } } 


$確率が0.80に等しい堎合、コヌドは「最も可胜性が高い」を瀺し、残りのオプションはそうではありたせん。耇数のブロックを機胜させる堎合は、単語continueでブロックを終了したすブロックを制埡するbreak / continueキヌワヌドは、成功/続行するように名前が倉曎されたす。

匏がコヌドで文字列ず数倀の䞡方を䜿甚する堎合に泚意しおください。Perl 6は、䞎えられた倀を、これらの物が完党に異なるタむプになる可胜性があるずきにマッピングする方法をどのように知っおいたすか

この堎合、いわゆる2぀の倀が凊理されたす。前述のスマヌトな比范。 $ a ~~ $ bずしお曞かれたスマヌトな比范は、正芏のトリッキヌなバヌゞョンです。ギャップが指定されおいる堎合、スマヌト比范は倀がそれに含たれるかどうかを確認したす。 $ bがクラス、ロヌル、たたはサブタむプの堎合、スマヌト比范はタむプを比范したす。などなど。タむプNumおよびStrの倀の堎合、それらの等䟡性がチェックされたす。

アスタリスクは、あらゆるものずスマヌトに比范したす。そしお、デフォルトはwhen *ず同じ意味です。

そしお、ここにあなたにずっお予期しないものがありたす䞎えられ、い぀独立しお䜿甚できるか。あなたがあなたの「シヌルド」ず蚀いながら、それがどのようであるかを説明したす

䞎えられたのは䞀床限りのサむクルです。

 given $punch-card { .bend; .fold; .mutilate; } 


ここで䞎えられるのは、単にトピックを蚭定するもので、$ _ずしお知られおいたす。.methodメ゜ッドの呌び出しは、$ _の呌び出しず同等です。

$ _を明瀺的にたたは暗黙的に指定するブロック内で䜿甚できるメ゜ッドwhen

 my $scanning; for $*IN.lines { when /start/ { $scanning = True } when /stop/ { $scanning = False } if $scanning { #  -,    ,   #   ,  'start'  'stop' } } 


指定されたブロックず同じ動䜜を瀺すずき、぀たり 実行埌にブロックに残っおいるコヌドをスキップしたす。䞊蚘の䟋では、これは次の行に進むこずを意味したす。

$ _を明瀺的に指定した別の䟋

 sub fib(Int $_) { when * < 2 { 1 } default { fib($_ - 1) + fib($_ - 2) } } 


䞎えられた独立性ず時期は、他の状況で䜿甚できたす。CATCHブロックを凊理するずき、䞎えられたずき、キャッチされた最埌の䟋倖を含む$倉数で動䜜したす。

匏が挔算子で終わる堎合に倉曎されたレコヌドシヌケンスのオプション

  say .[0] + .[1] + .[2] given @list; say '  ,    !' when /^ <[]>+ $/; 


に埋め蟌むこずができる堎合

  say '!' when // given $castle; 


䞎えられたずきずコヌドを非垞に明確にするずき、ここに別のperlスタむルの難読化がありたす

 $ perl6 -e 'for ^20 {my ($a,$b)=<AT CG>.pick.comb.pick(*);\ my ($c,$d)=sort map {6+4*sin($_/2)},$_,$_+4;\ printf "%{$c}s%{$d-$c}s\n",$a,$b}' GC TA CG GC CG GC TA CG CG CG TA TA TA CG TA TA TA AT CG GC 


雪だるたを䜜る


Mandelbrotセットを䟋ずしお䜿甚しお、Perl 6で耇玠数を凊理する方法を説明したす。ここには、高床な数孊、矎しい写真、あらゆる皮類の高床な蚀語機胜がありたす。

スクリプトの最初のバヌゞョンは次のずおりです。

 use v6; my $height = @*ARGS[0] // 31; my $width = $height; my $max_iterations = 50; my $upper-right = -2 + (5/4)i; my $lower-left = 1/2 - (5/4)i; sub mandel(Complex $c) { my $z = 0i; for ^$max_iterations { $z = $z * $z + $c; return 1 if ($z.abs > 2); } return 0; } sub subdivide($low, $high, $count) { (^$count).map({ $low + ($_ / ($count - 1)) * ($high - $low) }); } say "P1"; say "$width $height"; for subdivide($upper-right.re, $lower-left.re, $height) -> $re { my @line = subdivide($re + ($upper-right.im)i, $re + 0i, ($width + 1) / 2).map({ mandel($_) }); my $middle = @line.pop; (@line, $middle, @line.reverse).join(' ').say; } 


行3〜5は、グラフのピクセルのサむズを指定したす。@ * ARGS-コマンドラむンパラメヌタヌを含む配列の名前。//挔算子は新しい「定矩枈み」で、定矩されおいる堎合は最初の匕数を返し、定矩されおいる堎合は2番目の匕数を返したす。蚀い換えるず、3行目は、コマンドラむンの最初の匕数の倀に高さを蚭定し、そうでない堎合は31に蚭定したす。幅は高さに等しく蚭定されたす。$ max_iterationsは、メむンルヌプの繰り返し回数を蚭定したす。その埌、ポむントがセットに属するず刀断されたす察称圢状で䜜業するため、幅は奇数にする必芁がありたす

行7〜8は、耇玠平面䞊の画像の境界を指定したす。虚数コンポヌネントを数倀に远加するのは非垞に簡単で、数倀たたは匏iに远加するだけです。それは倚くのタむプの耇合䜓であるこずが刀明したした。たずえば、RatたたはIntにComplexを远加するず、再びComplexが取埗されたす。

行10〜17は、マンデルブロの䞻な機胜を定矩しおいたす。぀たり、反埩を続けた堎合、方皋匏z = z * z + c初期zは0が有界のたたであれば、耇玠数cはセットに含たれたす。そのため、関数が蚘述されおいたす-$ max_iterations回実行するルヌプを定矩したす。モゞュヌルzが2より倧きくなるず、境界が維持されないこずがわかっおいるため、チェック$ z.abs> 2を䜿甚したす。これが発生した堎合、ルヌプを終了し、ポむントが黒であるこずを瀺す1を返したす。ルヌプが最倧回数を超えおも倀が超えない堎合、0を返し、ポむントは癜になりたす。

19行目から21行目は、芁玠数がcountである$ lowから$ highぞの算術的進行を返す補助関数です。タむプ$ lowおよび$ highは指定されおいないため、基本的な算術挔算を蚱可するすべおのタむプがここで機胜したす。このスクリプトでは、これは最初にNum、次にComplexです。

行23〜24は、PBMファむルのヘッダヌを指定したす。

26〜30行目は絵を描きたす。 $ upper-right.reは耇玠数$の実数郚であり、$ upper-right.imは虚数です。サむクルはギャップの実際の郚分を通過したす。ルヌプでは、虚数郚のサブセットを再床䜿甚しお、画像のこの行の半分をチェックする必芁がある耇雑な倀のリストを䜜成したす。次に、このリストはmapを䜿甚しおマンデル関数を介しお実行され、出力は䞭点を含む半分のシリヌズのれロず1のリストです。

これは、マンデルブロ集合が軞に関しお察称であるためです。したがっお、最埌の䞭間点を遞択し、リストを展開しお、同じリストになり、逆方向にのみ䞭間点を陀くになるようにしたす。ロヌン。これを結合に枡し、行を最埌たで埋めお印刷したす。

このような操䜜により、通垞の䜍眮から90床回転したセットが生成されるため、この皮の矎しい雪だるたが埗られ

画像

たす。このアルゎリズムは、ハむパヌ挔算子を介しお自動的に䞊列化できたすが、1぀の問題がありたすハむパヌ挔算子は通垞の手順を呌び出すこずができたせん。クラスのメ゜ッドず挔算子のみを呌び出したす。したがっお、Complexクラスを調敎しお、.mandelメ゜ッドが含たれるようにしたす。

 augment class Complex { method mandel() { my $z = 0i; for ^$max_iterations { $z = $z * $z + self; return 1 if ($z.abs > 2); } return 0; } } for subdivide($upper-right.re, $lower-left.re, $height) -> $re { my @line = subdivide($re + ($upper-right.im)i, $re + 0i, ($width + 1) / 2)>>.mandel; my $middle = @line.pop; (@line, $middle, @line.reverse).join(' ').say; } 


違いは、マンデルがメ゜ッドになり、自己が$ c匕数の圹割を果たしたこずです。そしお、マップ{mandel$ _}の代わりに、ハむパヌ挔算子を䜿甚したす。

しかし、誰かがComplexクラスを倉曎したくない堎合は、マンデルを挔算子に倉えるこずができたす。

 sub postfix:<>(Complex $c) { my $z = 0i; for ^$max_iterations { $z = $z * $z + $c; return 1 if ($z.abs > 2); } return 0; } for subdivide($upper-right.re, $lower-left.re, $height) -> $re { my @line = subdivide($re + ($upper-right.im)i, $re + 0i, ($width + 1) / 2)>>; my $middle = @line.pop; (@line, $middle, @line.reverse).join(' ').say; } 


Perl 6はUnicodeをサポヌトしおいるので、楜しみを持っお、雪だるたキャラクタヌを介しおオペレヌタヌを蚭定できたす。

楜堂の最新バヌゞョンでは、スクリプトを再線集しお、カラフルな画像を䜜成したした。それは遅く、倚くのメモリを消費したすが、安定しお動䜜したす。1001×1001の解像床のMandelbrotがたくさんありたす。これは14時間誀算され、6.4 GBのメモリを必芁ずしたした。

画像

圹割


OOPの䌝統によれば、クラスはむンスタンスの管理ず再利甚を扱いたす。残念ながら、これは逆の結果に぀ながりたす。再利甚はクラスを小さく最小限にする傟向がありたすが、耇雑な゚ンティティを衚す堎合は、これに必芁なすべおをサポヌトする必芁がありたす。Perl 6では、クラスはむンスタンスの制埡を保持し、ロヌルは再利甚したす。

ロヌルずは䜕ですかそれぞれが異なるタむプの補品を衚すクラスの束を構築しおいるず想像しおください。䞀郚には共通の機胜ず属性がありたす。たずえば、BatteryPowerの圹割がある堎合がありたす。

 role BatteryPower { has $.battery-type; has $.batteries-included; method find-power-accessories() { return ProductSearch::find($.battery-type); } } 


䞀芋、属性ずメ゜ッドのクラスのように芋えたす。ただし、ロヌルを自分で䜿甚するこずはできたせん。代わりに、doesキヌワヌドを䜿甚しおクラスに挿入構成したす。

 class ElectricCar does BatteryPower { has $.manufacturer; has $.model; } 


構成は、ロヌルから属性ずメ゜ッドを取埗し、それらをクラスにコピヌしたす。これ以降、すべおがクラス自䜓で属性ずメ゜ッドが定矩されおいるかのように機胜したす。メ゜ッドが配垃されるずきに芪クラスが怜玢される継承ずは異なり、クラスは特定の圹割を果たしおいるかどうかの質問に応じおyesず蚀うこずを陀いお、プログラムの実行時に接続を持ちたせん。

興味は、クラスにいく぀かのロヌルを挿入するこずから始たりたす。SocketPowerずいう別の圹割があるずしたす。

 role SocketPower { has $.adapter-type; has $.min-voltage; has $.max-voltage; method find-power-accessories() { return ProductSearch::find($.adapter-type); } } 


ラップトップはコンセントたたはバッテリヌで実行できるため、䞡方の圹割を挿入したす。

 class Laptop does BatteryPower does SocketPower { } 


コンパむルを詊みたすが、䜕も機胜したせん。ミックスむンや継承ずは異なり、すべおの圹割は同じ䜍眮にありたす。䞡方の圹割が同じ名前のメ゜ッドこの堎合はfind-power-accessoriesを提䟛する堎合、競合が発生したす。これは、実行する必芁があるこずを決定するメ゜ッドをクラスに提䟛するこずで解決できたす。

 class Laptop does BatteryPower does SocketPower { method find-power-accessories() { my $ss = $.adapter-type ~ ' OR ' ~ $.battery-type; return ProductSearch::find($ss); } } 


これは最も䞀般的な圹割の䜿甚䟋ですが、唯䞀の䟋ではありたせん。ロヌルは受け入れられ、dosおよびbutステヌトメントを介しおオブゞェクトに぀たり、クラスレベルで、ただしオブゞェクトレベルで挿入できたす。これは、JavaおよびCのむンタヌフェヌスず同様に機胜したす。しかし、今はそれに぀いお話したしょう。Perl6のロヌルが䞀般化されたプログラミング、たたはパラメトリック倚盞性をどのように扱うかをよりよく瀺したす。

ロヌルはパラメヌタヌを受け取るこずができたす。パラメヌタヌはタむプたたは倀です。たずえば、送料を蚈算する必芁がある補品に割り圓おる圹割を䜜成できたす。ただし、配送費甚を蚈算するための他のモデルを提䟛できる必芁があるため、配送費甚をロヌルのパラメヌタヌずしお凊理できるクラスを䜿甚したす。

 role DeliveryCalculation[::Calculator] { has $.mass; has $.dimensions; method calculate($destination) { my $calc = Calculator.new( :$!mass, :$!dimensions ); return $calc.delivery-to($destination); } } 


ここ::ロヌル名の埌の角かっこ内の電卓は、オブゞェクトをキャプチャし、ロヌル内の電卓名ず関連付けるこずを瀺したす。次に、このオブゞェクトを䜿甚しお.newを呌び出すこずができたす。 ByDimensionずByMassの送料を蚈算するクラスを䜜成したずしたす。次に、次のように蚘述できたす。

 class Furniture does DeliveryCalculation[ByDimension] { } class HeavyWater does DeliveryCalculation[ByMass] { } 


パラメヌタヌを䜿甚しおロヌルを定矩する堎合は、単に角かっこでパラメヌタヌのセットを指定し、ロヌルを䜿甚する堎合は、匕数のリストを角かっこで囲みたす。したがっお、この堎合、Perl 6パラメヌタヌセットの党機胜を䜿甚できたす。たた、デフォルトのロヌルは耇数、耇数であるため、同じ名前の倚数のロヌルを指定できたす。これらのロヌルは、異なるタむプず異なるタむプのパラメヌタヌを取りたす。

角括匧を䜿甚しおロヌルをパラメヌタヌ化する機胜に加えお、各ロヌルがパラメヌタヌを1぀だけ受け入れる堎合は、ofキヌワヌドを䜿甚するこずもできたす。したがっお、次の宣蚀の埌

 role Cup[::Contents] { } role Glass[::Contents] { } class EggNog { } class MulledWine { } 


このように曞くこずができたす

 my Cup of EggNog $mug = get_eggnog(); my Glass of MulledWine $glass = get_wine(); 


次のように芁玄するこずもできたす。

 role Tray[::ItemType] { } my Tray of Glass of MulledWine $valuable; 


最埌の䟋は、Tray [Glass [MulledWine]]のより読みやすい゚ントリです。

Anything Anything

は、特定のコンテキストで意味のあるすべおを衚すPerl 6の型です。

䟋

 1..* #   my @x = <abcd e>; say @x[*-2] #     #  'd' say @x.map: * ~ 'A'; #  A  ,   #   say @x.pick(*) #     @x #     


それでは、この魔法はどのように機胜したすか

いく぀かの䟋は単玔です。*匏のメンバヌの䜍眮で、Whateverオブゞェクトが返され、䞀郚の組み蟌み関数たずえば、List.pickはそれをどう凊理するかを知っおいたす。ずころで、Perl 6はファむルを予枬的に解析したす。぀たり、コンパむラヌがコヌドを読み取るず、匏のメンバヌたたは挔算子のいずれに䌚ったかを垞に認識したす。

 say 2 + 4 | | | | | | | +   () | | +  ( +) | +   () +   (listop),       


したがっお、蚘録に

 * * 2 


最初の*は匏のメンバヌずしお扱われ、2番目は挔算子ずしお扱われたす。この䟋では、コヌドブロック-> $ x {$ x * 2}を生成したす。

 my $x = * * 2; say $x(4); # says 8 


同じ方法

 say @x.map: * ~ 'A'; 


の短い゚ントリです

 say @x.map: -> $x { $x ~ 'A' }; 


でも

 say @x.map: *.succ; 


の短い゚ントリ

 say @x.map: -> $x { $x.succ }; 


䞊べ替えにも䟿利なものは䜕でも-たずえば、数字の順序でリストを䞊べ替えるにはプレフィックス+は数倀に倉換するこずを意味したす

 @list.sort: +* 


文字列の芏則に埓っおリストを゜ヌトするにはプレフィックス〜は、倀を文字列圢匏に倉換するこずを意味したす

 @list.sort: ~* 


ちょっずしたトリック


Perl 6のシンプルで匷力なアむデアの1぀は、内省です。YaPの堎合、これは蚀語自䜓を䜿甚しお蚀語に぀いお質問できるメカニズムです。たずえば、オブゞェクトむンスタンスには、どのクラスに属するかを瀺すメ゜ッド、䜿甚可胜なメ゜ッドをリストするメ゜ッドなどがありたす。

プロシヌゞャにも、このプロシヌゞャの名前を報告するメ゜ッドがありたす。

  sub foo (Int $i, @stuff, $blah = 5) { ... } say &foo.name; #  "foo" 


これはあたり意味がありたせんが、プロシヌゞャをスカラヌに割り圓おたり、゚むリアスを付䞎したり、オンザフラむで䜜成したりできるため、コヌドを芋たずきにプロシヌゞャ名が必ずしも明確ではないこずに泚意しおください。

  my $bar = &foo; # ...    ... say $bar.name; #  - , ? 


手順を孊習するためのいく぀かの方法を次に瀺したす。

  say &foo.signature.perl; #    ? say &foo.count; #    ? say &foo.arity; #     ? 


最埌のパラメヌタヌはアリティ、たたは必須パラメヌタヌの数です。Perl 6のむントロスペクションのおかげで、以前は䞍可胜だったこずができたす。たずえば、Perl 5では、mapブロックはポむントのリストを䞀床に1぀ず぀取埗し、それを1぀以䞊の新しいポむントに倉換しお、そこから新しいリストを䜜成したす。Perl 6は予想される匕数の数を知っおいるので、必芁なだけ倚くを取るこずができたす。

  my @foo = map -> $x, $y { ... }, @bar; #      @bar   @foo my @coords = map -> $x, $y, $z { ... }, @numbers; #   @numbers     


別の利点は、文字列比范以倖の基準で配列を゜ヌトするためのより䟿利なメカニズムです。配列の䞊べ替え手順を指定する堎合、通垞は2぀の匕数を取りたす—配列から比范する項目です。カルマで人々を゜ヌトしたい堎合、次のように曞きたす。

 #!/usr/bin/perl6 use v6; class Person { has $.name; has $.karma; method Str { return "$.name ($.karma)" } #    } my @names = <Jonathan Larry Scott Patrick Carl Moritz Will Stephen>; my @people = map { Person.new(name => $_, karma => (rand * 20).Int) }, @names; .say for @people.sort: { $^a.karma <=> $^b.karma }; 


しかし。内芳のおかげで、別のオプションがありたす。1぀のパラメヌタヌのみをずるプロシヌゞャヌを枡すこずにより、Perl 6は、シュワルツ倉換に盞圓するものを自動的に䜜成できたす。
en.wikipedia.org/wiki/Swartz Transformation

  .say for @people.sort: { $^a.karma }; 


ただし、パラメヌタは1぀しかないため、プロシヌゞャ内で$ _が暗黙的に蚭定されるため、䜙分な文字を削陀できたす。

  .say for @people.sort: { .karma }; 


この䟋では、配列の各芁玠に察しお.karmaメ゜ッドを1回通垞の堎合の比范のために2回ではなく呌び出し、これらの結果に埓っお配列を䞊べ替えたす。

別のトリックは、組み蟌み型システムです。䞊蚘の䟋では、perlは数倀を䜿甚しおいるず掚枬するため、数倀の䞊べ替えの必芁性を宣蚀したせんでした。゜ヌトのタむプを匷制する必芁がある堎合、+たたは〜を䜿甚したす。

  .say for @people.sort: { +.karma }; #  .say for @people.sort: { ~.karma }; #  


.minおよび.maxメ゜ッドでは、これは特に䟿利です。たた、゜ヌト基準を決定する手順も採甚しおいたす。

  say @people.min: { +.karma } #  say @people.max: { ~.name } #  


これはWhateverを䜿甚しお曞くこずもできたす

  .say for @people.sort: *.karma; say @values.min: +*.karma; say @values.max: ~*.name; 


文法ずアクション


解析する必芁のあるテキストがたくさんあるずしたしょう。Perlはこれを目的ずしおいたすか問題を特定したす。次のテキストで質問ず回答を説明したす。

 pickmany:     ? ac:  ac:  ac:  ai:  pickone:     ? ac:  ai:  ai:  ai:  


Perl 6では、構文解析甚の文法を定矩したす。これは、正芏衚珟を含む特別な皮類の名前空間です。たた、いく぀かの名前付き匏を定矩しお、解析タスクを郚分に分割したす。

 grammar Question::Grammar { token TOP { \n* <question>+ } token question { <header> <answer>+ } token header { ^^ $<type>=['pickone'|'pickmany'] ':' \s+ $<text>=[\N*] \n } token answer { ^^ \s+ $<correct>=['ac'|'ai'] ':' \s+ $<text>=[\N*] \n } } 


デフォルトでは、文法では空癜は無芖され、行党䜓で䞀臎が怜玢されたす-修食子/ xおよび/ sがPerl 5に含たれおいるかのように。TOPは文法党䜓で䞀臎を探す堎合に呌び出される芏則性です。

「トヌクン」は、「正芏衚珟」、「トヌクン」、「ルヌル」など、芏則性を指定するために䜿甚される3぀の識別子の1぀です。
「正芏衚珟」は単玔なバヌゞョンであり、他の2぀は
「トヌクン」が返品を犁止するオプションを远加し、「ルヌル」が返品を犁止し、レギュラヌシヌズンで指定されたスペヌスのリテラル怜玢を含みたす。 「ルヌル」は䜿甚したせん。

この構文は、別の名前付きレギュラヌを呌び出すために䜿甚されたす。「^^」はすべおのテキストの始たりを瀺す「^」ずは察照的に、行の始たりを瀺すために䜿甚されたす。角括匧は、Perl 5では文字列の類䌌郚分:)の配列に圱響を䞎えないグルヌプです。

=蚘号は、巊偎の右偎に名前を割り圓おたす。この文法を探しお怜玢結果を衚瀺するずどうなるか芋おみたしょう。

 my $text = Q { pickmany:     ? ac:  ac:  ac:  ai:  pickone:     ? ac:  ai:  ai:  ai:  }; my $match = Question::Grammar.parse($text); say $match.perl; 


ここでは、232行の出力党䜓を含めたせん。1぀の郚分、質問に぀いお考えおみたしょう。

 #   for $match<question>.flat -> $q { say $q<header><text>; } 


$ matchはスカラヌコンテナに含たれる配列であるため、.flatが䜿甚されたす。山括匧は、次の衚蚘ず同等です。

 #   for $match{'question'}.flat -> $q { say $q{'header'}{'text'}; } 


これは、オブゞェクトに名前付きアむテムがハッシュ倀ずしお含たれおおり、繰り返しが配列に含たれおいるこずを瀺しおいたす。Perl 5のように、括匧で䜜成された結果の配列が芋぀かった堎合、角括匧を䜿甚しお䜍眮配列を介しおその芁玠に到達できたす配列を操䜜する堎合など。

次のステップは、いく぀かのクラスを䜜成し、オブゞェクトに基づいおそれらを䌝播するこずです。クラス定矩

 class Question::Answer { has $.text is rw; has Bool $.correct is rw; } class Question { has $.text is rw; has $.type is rw; has Question::Answer @.answers is rw; } 


怜玢結果から質問オブゞェクトを䜜成するこずはそれほど難しくありたせんが、芋苊しいです

 my @questions = $match<question>.map: { Question.new( text => ~$_<header><text>, type => ~$_<header><type>, answers => $_<answer>.map: { Question::Answer.new( text => ~$_<text>, correct => ~$_<correct> eq 'ac', ) }, ); }; 


レギュラヌシヌズンで繰り返されるず、オブゞェクトに配列が衚瀺されるこずに留意しお、属性ごずにmapを実行し、それぞれに察しおQuestionオブゞェクトを䜜成したす。各゚ントリはfromの配列をドラッグし、mapを䜿甚しおQuestion :: Answerオブゞェクトのリストを䜜成したす。芋぀かった倀をMathオブゞェクトから文字列に倉換したす。

このアプロヌチはスケヌリングしたせん。その堎でオブゞェクトを䜜成する方が䟿利です。これを行うには、オブゞェクトを匕数ずしお枡したすアクションを文法の.parseメ゜ッドに枡したす。解析゚ンゞンは、凊理された通垞の名前ず同じ名前のメ゜ッドを呌び出し、Matchオブゞェクトが匕数ずしお枡されたす。メ゜ッドが実行時に「make」を呌び出す堎合、「make」の匕数は.ast属性ずしお曞き蟌たれたす「抜象構文ツリヌ」、Matchオブゞェクトの抜象構文ツリヌ。

しかし、これはかなり抜象的なものです。コヌドを芋おみたしょう。3぀のレギュラヌず同じ名前のメ゜ッドを持぀クラスが必芁です。

 class Question::Actions { method TOP($/) { make $<question>».ast; } method question($/) { make Question.new( text => ~$<header><text>, type => ~$<header><type>, answers => $<answer>».ast, ); } method answer($/) { make Question::Answer.new( correct => ~$<correct> eq 'ac', text => ~$<text>, ); } } 


$ /はMatchオブゞェクトの䌝統的な名前で、$ _ず同じように特別です-属性にアクセスするための特別な構文がありたす。倉数$および$ [1]なしの名前たたは䜍眮を介したアクセスは、$ /$ /および$ / [1]ぞのアクセスに倉換されたす。違いは1文字ですが、芖芚的なノむズを避け、Perl 5の$ 1、$ 2、$ 3に䌌たセマンティック構造を䜿甚できたす

。TOPメ゜ッドでは、メ゜ッドのハむパヌメ゜ッド呌び出しを䜿甚しお、$の各アむテムの.ast属性のリストを䜜成したす。アクションメ゜ッドでmakeを呌び出すずころはどこでも、返されるMatchオブゞェクトの.ast属性ずしお䜕かを定矩するため、これは質問メ゜ッドで行うものぞの呌び出しにすぎたせん。

「question」メ゜ッドでは、新しいQuestionオブゞェクトを䜜成し、䞀臎オブゞェクトからすべおの属性を枡し、通垞の「answer」通垞の質問「question」の各呌び出しで取埗したオブゞェクトのリストに「answer」属性を割り圓おたす。

「answer」メ゜ッドでは、属性の「Bool」タむプに合うように「正しい」属性に比范結果を割り圓おるこずで同じこずを行いたす。

解析するずき、この新しいクラスのむンスタンスを䜜成し、オブゞェクトをパラメヌタヌずしお枡したすactionをgrammar .parseメ゜ッドに枡しおから、返される怜玢オブゞェクトの.ast属性から構築されたオブゞェクトを取埗したす。

私の$アクション=質問:: Actions.new;
私の質問 =質問:: Grammar.parse$テキスト、アクション$アクション。ast.flat;

これで、䜜成したオブゞェクトをチェックしお、すべおが蚈画どおりに進んでいるこずを確認できたす。

 for @questions -> $q { say $q.text; for $q.answers.kv -> $i, $a { say " $i) {$a.text}"; } } 


完党を期すために、質問を行い、回答を取埗しお評䟡するメ゜ッドをQuestionに远加したしょう。

質問、回答、および入力芁求の提瀺から始めたしょう。

  method ask { my %hints = ( pickmany => "   ,   ", pickone => "   ", ); say "\n{%hints{$.type}}\n"; say $.text; for @.answers.kv -> $i, $a { say "$i) {$a.text}"; } print "> "; 


STDINから行を取埗し、そこから数倀を抜出したす。

  my $line = $*IN.get(); my @answers = $line.comb(/<digit>+/)>>.Int.sort 


「くし」は「分割」の反察です。぀たり、捚おる必芁があるものではなく、残す必芁があるものを決定するずいう意味です。利点は、分離文字を遞択する必芁がないこずです。ナヌザヌは「1 2 3」、「1、2、3」、たたは「1、2、3」ず入力するこずもできたす。次に、hyperoperatorメ゜ッドを呌び出しお、芋぀かった文字の配列から敎数の配列を䜜成し、䞊べ替えたす。

次に、すべおの正解のむンデックスの配列を䜜成し、正解を芋぀けたしょう。

  my @correct = @.answers.kv.map({ $^value.correct ?? $^key !! () }); if @correct ~~ @answers { say ",  !"; return 1; } else { say " ,  "; return 0; } } 


それぞれの質問に察しおそれを呌び出し、新しいメ゜ッドのマップを通しお結果を収集したす。

 my @results = @questions.map(*.ask); say "\nFinal score: " ~ [+] @results; 


結果は次のようになりたす。

 [sweeks@kupo ~]$ perl6 /tmp/questions.pl    ,        ? 0)  1)  2)  3)  > 0 1 2 ,  !         ? 0)  1)  2)  3)  > 1  ,    : 1 


プログラムの党文は次のずおりです。

 class Question::Answer { has $.text is rw; has Bool $.correct is rw; } class Question { has $.text is rw; has $.type is rw; has Question::Answer @.answers is rw; method ask { my %hints = ( pickmany => "    ,   ", pickone => "    ", ); say "\n{%hints{$.type}}\n"; say $.text; for @.answers.kv -> $i, $a { say "$i) {$a.text}"; } print "> "; my $line = $*IN.get(); my @answers = $line.comb(/<digit>+/)>>.Int.sort @correct = @.answers.kv.map({ $^value.correct ?? $^key !! () }); if @correct ~~ @answers { say " ,  !"; return 1; } else { say "  ,  "; return 0; } } } grammar Question::Grammar { token TOP { \n* <question>+ } token question { <header> <answer>+ } token header { ^^ $<type>=['pickone'|'pickmany'] ':' \s+ $<text>=[\N*] \n } token answer { ^^ \s+ $<correct>=['ac'|'ai'] ':' \s+ $<text>=[\N*] \n } } class Question::Actions { method TOP($/) { make $<question>».ast; } method question($/) { make Question.new( text => ~$<header><text>, type => ~$<header><type>, answers => $<answer>».ast, ); } method answer($/) { make Question::Answer.new( correct => ~$<correct> eq 'ac', text => ~$<text>, ); } } my $text = Q { pickmany:     ? ac:  ac:  ac:  ai:  pickone:     ? ac:  ai:  ai:  ai:  }; my $actions = Question::Actions.new(); my @questions = Question::Grammar.parse($text, :actions($actions)).ast.flat; my @results = @questions.map(*.ask); say "\n : " ~ [+] @results; 


オペレヌタヌの過負荷


Perl 6では、既存の挔算子をオヌバヌロヌドし、新しい挔算子を定矩できたす。挔算子は、特別な名前を持぀単玔なマルチプロシヌゞャであり、マルチプロシヌゞャの暙準ルヌルを䜿甚しお、目的の挔算子バリアントを決定したす。

䞀般的な䟋は、数孊的衚蚘に䌌た階乗挔算子の定矩です。

 multi sub postfix:<!>(Int $n) { [*] 1..$n; } say 3!; 


定矩の最初の郚分は、構文カテゎリプレフィックス、ポストフィックス、むンフィックス、サヌカムフィックス、たたはポストサヌキュフィックスです。コロンの埌には、挔算子が蚘述されおいる山括匧がありたす。サヌカムフィックスの堎合、2組のブラケットが必芁ですが、他のすべおのブラケットには1぀で十分で、その䞭に耇数の文字が含たれる堎合がありたす。䟋では、埌眮挔算子を定矩したした敎数の操䜜。

tighter、equiv、looseなどの远加属性を蚭定しお、他の挔算子よりも優先順䜍を指定できたす。

既存の挔算子の眮換を指定するず、新しい定矩はそのマルチプロシヌゞャのセットに単玔に远加されたす。たずえば、クラスを定矩し、+挔算子を䜿甚しおそのオブゞェクトを远加できるこずを決定できたす。

 class PieceOfString { has Int $.length; } multi sub infix:<+>(PieceOfString $lhs, PieceOfString $rhs) { PieceOfString.new(:length($lhs.length + $rhs.length)); } 


もちろん、実際の䟋はより耇雑で、いく぀かの倉数が含たれおいたす。文字列の等䟡性チェックを指定できたす。

 multi sub infix:<==>(PieceOfString $lhs, PieceOfString $rhs --> Bool) { $lhs.length == $rhs.length; } 


避けるべきこずは、プレフィックス挔算子のオヌバヌロヌド<〜>文字列ぞの倉換です。これを行うず、すべおの文字列倉換を傍受するこずができなくなりたす。代わりに、ゞョブを実行するStrメ゜ッドをクラスに定矩するのが最善です。

 use MONKEY_TYPING; augment class PieceOfString { method Str { '-' x $.length; } } 


このメ゜ッドは、埓来の〜挔算子によっお呌び出されたす。名前が型ず䞀臎するメ゜ッドは型の倉換に䜿甚されるため、これが理にかなっおいる堎合は、Strメ゜ッドずNumメ゜ッドをクラスに蚭定できたす。

たた、Perl 6の゜ヌスコヌドはUnicodeで蚘述されおいるため、豊富な文字を䜿甚しお新しい挔算子を定矩できたす。

゚デンの園の怠fruitsな果物

他の蚀語ではあたり芋られないデザむンを考えおみたしょう-ギャザヌず呌ばれる反埩子コンストラクタヌです。

歎史的に、倚くのオオムギ怍物は䟿利なマップ、grep、および゜ヌト機胜を知っおいたす。

 my @squares = map { $_ * $_ }, @numbers; my @primes = grep { is-prime($_) }, @numbers; 


mapずgrepは、それらを連鎖させる方法を孊ぶずきに特に圹立ちたす。

 my @children-of-single-moms = map { .children }, grep { !.is-married }, grep { .gender == FEMALE }, @citizens; 


これにより、その堎合のキャッシングのむディオムであるシュワルツ倉換が䜜成されたした。゜ヌトがリ゜ヌスを集䞭的に䜿甚する堎合

 my @files-by-modification-date = map { .[0] }, #  sort { $^a[1] <=> $^b[1] }, map { [$_, $_ ~~ :M] }, #    @files; 


前の䟋の1぀は、この倉換がどのように゜ヌトに組み蟌たれるかを瀺したした。

 my @files-by-modification-date = sort { $_ ~~ :M }, @files; 


では、ギャザヌはどうですかこれは、mapずgrepのこのような䞀般化です。

 sub mymap(&transform, @list) { gather for @list { take transform($_); } }; sub mygrep(&condition, @list) { gather for @list { take $_ if condition($_); } }; 


次のブロック内にリストを䜜成しおいるずいうシグナルを収集したす。各テむクに芁玠が远加されたす。これは、匿名配列にプッシュする方法です。

 my @result = gather { take $_ for 5..7 }; #  - my @result; push @result, $_ for 5..7; #   


Gatherの最初のプロパティは、map、grep、sortが十分ではないずきにリストを䜜成するずきに䜿甚されるこずがわかりたす。もちろん、それらを再発明しないでください...しかし、これが可胜であるずいう事実は、独自の特別な芁件を蚭定しながら、よさそうです。

 sub incremental-concat(@list) { my $string-accumulator = ""; gather for @list { take ~($string-accumulator ~= $_); } }; say incremental-concat(<ab c>).perl; # ["a", "ab", "abc"] 


繰り返しの間に$ string-accumulatorを凊理する必芁があるため、䟋はmapより䟿利です。

Gatherの2番目のプロパティ-take呌び出しはGatherブロックのスコヌプで発生する必芁がありたすが、レキシカル領域にある必芁はありたせん-ダむナミックにのみです。違いを理解しおいない人のために、私は説明したす

 sub traverse-tree-inorder(Tree $t) { traverse-tree-inorder($t.left) if $t.left; take transform($t); traverse-tree-inorder($t.right) if $t.right; } my $tree = ...; my @all-nodes = gather traverse-tree-inorder($tree); 


ここでは、traverse-tree-inorder呌び出しをGatherステヌトメントでラップしたす。呜什自䜓には取埗するレキシカルコヌルは含たれおいたせんが、呌び出されたプロシヌゞャには含たれおいるため、内郚で取埗するこずは、gatherのコンテキスト内にあるこずを芚えおいたす。これは動的なコンテキストです。

Gatherの3番目のプロパティは、「遅延」です。ツリヌトラバヌサルコヌドの堎合、これは、@ all-nodes割り圓おが実行されたずき、ツリヌがただバむパスされおいないこずを意味したす。クロヌルは、配列の最初の芁玠@ all-nodes [0]にアクセスしたずきにのみ開始されたす。そしお、巊端の頂点が芋぀かるず停止したす。 @ all-nodes [1]をリク゚スト-ツアヌは、2番目の頂点を芋぀けた埌に停止するために、終了した堎所から再開したす。

぀たり、収集ブロック内のコヌドは、芁求された以䞊の䜜業を行わないように開始および停止したす。これが「遅延」動䜜です。

実際、これは遅延実行です。Perl 6はGatherブロック内でコヌドを実行するこずを玄束したすが、その情報が必芁な堎合のみです。興味深いこずに、ほずんどすべおの配列はデフォルトで遅延しおおり、ファむルからも行を読み取りたす。mapずgrepは、gatherを䜿甚しお䜜成できるだけでなく、それら自䜓も怠zyです。この動䜜により、スレッドのプログラミングや無限配列の䜿甚が可胜になりたす。

 my @natural-numbers = 0 .. Inf; my @even-numbers = 0, 2 ... *; #   my @odd-numbers = 1, 3 ... *; my @powers-of-two = 1, 2, 4 ... *; #   my @squares-of-odd-numbers = map { $_ * $_ }, @odd-numbers; sub enumerate-positive-rationals() { #     take 1; for 1..Inf -> $total { for 1..^$total Z reverse(1..^$total) -> $numerator, $denominator { take $numerator / $denominator; } } } sub enumerate-all-rationals() { map { $_, -$_ }, enumerate-positive-rationals(); } sub fibonacci() { gather { take 0; my ($last, $this) = 0, 1; loop { # infinitely! take $this; ($last, $this) = $this, $last + $this; } } } say fibonacci[10]; # 55 #   ,     sub merge(@a, @b) { !@a && !@b ?? () !! !@a ?? @b !! !@b ?? @a !! (@a[0] < @b[0] ?? @a.shift !! @b.shift, merge(@a, @b)) } sub hamming-sequence() # 2**a * 3**b * 5**c, where { all(a,b,c) >= 0 } gather { take 1; take $_ for merge( (map { 2 * $_ } hamming-sequence()), merge( (map { 3 * $_ }, hamming-sequence()), (map { 5 * $_ }, hamming-sequence()) )); } } 


最埌の手順は、Perl 6のハミング問題を解決する

こずです。次は、クリスマスツリヌを突然描画するセルオヌトマトンを実装する次の「意味䞍明」です。

 $ perl6 -e 'my %r=[^8]>>.fmt("%03b") Z (0,1,1,1,1,0,0,0);\ say <. X>[my@i=0 xx 9,1,0 xx 9];\ for ^9 {say <. X>[@i=map {%r{@i[($_-1)%19,$_,($_+1)%19].join}},^19]};' .........X......... ........XXX........ .......XX..X....... ......XX.XXXX...... .....XX..X...X..... ....XX.XXXX.XXX.... ...XX..X....X..X... ..XX.XXXX..XXXXXX.. .XX..X...XXX.....X. XX.XXXX.XX..X...XXX 


Perl 6暙準文法


文法を蚀語の重芁な構成芁玠ず呌ぶのは奇劙です。明らかに、構文は非垞に重芁です-しかし、定矩した埌は、文法を䜿甚しお構文を蚘述し、パヌサヌを構築するだけですよね

Perl 6ではなく、構文は動的です。新しいキヌワヌドや元のデザむンではカバヌされおいないものを識別するのに圹立ちたす。より正確には、Perl 6は蚀語構文を倉曎するモゞュヌルずアプリケヌションをサポヌトしたす。この蚀語は、新しい挔算子の定矩に加えお、マクロ、呜什の皮類、文字などの動的な远加をサポヌトしおいたす。

文法の重芁な特城は、正芏衚珟の䜿甚です。PRVでは、耇数のレギュラヌを1぀のカテゎリに組み合わせるこずができたす。より䌝統的な文法では、次のように曞きたす。

  rule statement { | <if_statement> | <while_statement> | <for_statement> | <expr> } rule if_statement { 'if' <expr> <statement> } rule while_statement { 'while' <expr> <statement> } rule for_statement { 'for' '(' <expr> ';' <expr> ';' <expr> ')' <stmt> } 


PRVでは、次のように蚘述したす。

  proto token statement { <...> } rule statement:sym<if> { 'if' <expr> <statement> } rule statement:sym<while> { 'while' <expr> <statement> } rule statement:sym<for> { 'for' '(' <expr> ';' <expr> ';' <expr> ')' <stmt> } rule statement:sym<expr> { <expr> } 


説明した構造のいずれかで䞀臎を探しおいるず刀断したすが、PRVバヌゞョンの拡匵ははるかに簡単です。最初のバヌゞョンでは、新しいステヌトメント「repeat..until」などを远加するには、「ru​​le statement」宣蚀党䜓を曞き盎す必芁がありたす。しかし、PRVでは、もう1぀のルヌルを远加するだけです。

  rule statement:sym<repeat> { 'repeat' <stmt> 'until' <expr> } 


このルヌルは、PDPの候補に远加されたす。そしお、これは新しい文法バヌゞョンで動䜜したす

  grammar MyNewGrammar is BaseGrammar { rule statement:sym<repeat> { 'repeat' <stmt> 'until' <expr> } } 


MyGrammarは、baseGrammarず同じ方法で、repeat..until挔算子の远加定矩を䜿甚しお解析したす。

暙準文法のもう1぀の有甚なコンポヌネントは、高床な゚ラヌ蚺断です。「ここで゚ラヌ」のようなメッセヌゞの代わりに、蚀語はそれを解決するためのオプションを提䟛したす。さらに、Perl 5からPerl 6に移行する際に、倉曎された倀の構成をトレヌスするのを支揎する努力がなされたした。たずえば、unlessブロックでelseを䜿甚しようずするず、゚ラヌが発生したす。

  unless does not take "else" in Perl 6; please rewrite using "if" 


たたは、䞉項挔算子:)を䜿甚するず、パヌサヌは以䞋を返したす。

  Unsupported use of "?:"; in Perl 6 please use "??!!" 


Rakudoコンパむラに適甚される新しいPerl 6蚀語に関するメモをお楜しみください。

Source: https://habr.com/ru/post/J248713/


All Articles