百聞は一見にしかずというわけでPugs

Perl 6の実装の1つ、Pugsを入れてみた。
そもそもPerlの実装はいままでperlしかなかった。
ActivePerlにしても実はperlをコンパイルしてあるだけでしょう。
まぁところが、Perl 6においては、Pugsという形でperlより早くPerl 6を実現してると。


導入だが、Windowsの場合、ActivePerl 5.8が必要。
ActivePerl 5.10では無理でした。
しゃあないのでActivePerl 5.8のZIPを落としてきて、
それのperl58.dllをC:\perl\binに置いた。なぜかこれだけで動く。
しかしPugsで遊びたいならActivePerl 5.8を普通にインストールすればOK。
あと、PugsはHaskellというやつで作られているらしい。
その解釈にGHCが必要。
Pugsだがコンパイルがめんどくさいらしいのでバイナリを直接導入。
Jonathan Worthington :: Perl 6 / Parrot:よりWin32 Builds Of Pugsをダウンロード。
これを解凍して適当な場所に置いてパス通すなりすれば完成。
コマンドプロンプトからpugsとして起動すると、しばらくして対話的なコンソールが出てくる。
ここで実行してもいいですね。
あと、適当にfoo.p6とかいうファイルにスクリプト書いて、pugs foo.p6とかすれば実行できる。
けどpugsは初期化が遅いねぇ。Haskellは遅いからだとか書いてあるところあったけど。
まぁ理由はともあれ、遅いことは確かです。perlは高速だとうれしいですね。


資料が少なくて、よくわからんのだが、まぁつまみ食いすればいいですね。
Perl 6でもっともありがたいのがシジル言うらしいが、$@%&の取り扱いがよくなる。

my @a=(1..10);
say @a[5];
.say for(@a);
for @a->$x,$y{
($x,$y).perl.say;
}
my $ar=@a;
$ar[3].say;
for(0..^$ar) {
say "$_ $ar[$_]";
}
my %h=(john=>100,tom=>300,ken=>600);
%h{'tom'}.say;
%h.say;
%h=(700,800);
for(%h){
sprintf('%-4s %s', .key , .value).say
}

なんというか…下品なコード多いですね。
そうそう、Perl 6では変数宣言必須ですよ。Perl 5で言うuse strict;された状態。
なのでいちいちmyで宣言しましょう。
それで、@aの5番目というのは@a[5]と、$a[5]ではないと。
なるほどこれはわかりやすい。今まで説明に苦しみましたからね。
同様に$h{‘tom’}は%h{‘tom’}になります。
ただし、Perl 5では$h{john}が許容されてたけれど、Perl 6ではクオートで囲まなくてはいけない。
そこでqw()に相当する、<>の中に書けばいいらしい。
ただし空白文字を含まないことが条件です。そりゃそうですね。
さらにありがたいのが$ar[5]はPerl 5で$ar->[5]と書いてたことに相当する。
便利ですね。->は . に置き換えられるので、$ar.[5]となるわけですが、
この . は自明であるので省略されると。$foo->[5]->[2]の[5]と[2]の間のが省略可だったのと同じ事情。


forの使い方は今までと変わったり変わらなかったり。
foreachは廃止されたっぽいけど。けどforとforeachは意味一緒になってるし。
一番初めの例は超下品ですね。.say for(@a)ってなんだよと。
for(@a) { $_.say(); }と同じ意味です。
実行する文が1文ならfor修飾子を使うことができると。実行する文の最後にfor(@a)とか付けると。
$_.say()については、サブルーチンの括弧は省略できることもあるので省略。
そのうえ$_のメソッド、プロパティについては$_を省略して、結果.sayでいいと。
今まではprint $_;をprint;と省略してたけど、そうではないよということです。
次は上品な例です。for @aの後ろに->$x,$y{ }というブロックを付けてます。
->はコードブロックを作るのに使う。次に引数リスト、そして{ }のブロック。
for(1..10)->$i{ print $i,”\n”; }はPerl 5で言う、for my $i(1..10){ print $i,”\n”; }に相当します。
ところで引数2つ取るが、これは2つずつ回すこと。便利ですね。
もちろん今まで通り、for(@a) { }のように書いていいけど、
{の前に空白が必要なので注意。あと、Perl 6ではforの()は省略できます。
perlメソッドというのがどのオブジェクトにもあって、
これはオブジェクトをわかりやすく文字列に変換するメソッド。
この場合(1, 2)のように文字列化されます。
ハッシュをforで回すこともできます。
この場合取り出されるオブジェクトは長さ2の配列っぽい。が、それだけじゃない。
詳しい事情は理解できてないが、keyとvalueというプロパティを持ってる。
なので、$_.keyと$_.key、略して .keyと .valueを使えば便利?


$arに@aを代入するとどうなるでしょうか。
答えは@aのリファレンスが入ります。いままでなら配列の長さでしたけど。
一応今まで通り\@aでもリファレンスにできるみたい。
配列の長さは@a.elemsで、長さ-1は@a.endで得ます…
が、@aを数字のように取り扱えば長さは簡単に得られます。+@aとすればいいんです。
リファレンスでも$ar.elemsとか+$arとかで得られます。
さて、今まで0..$#aというのをよく使っていました。長さ-1というのはこれで必要だったの。
ところが、Perl 6では0..^@aとすればOKです。
範囲演算子に^を付けると、その端の値は含まないと。だから0..@a-1することと一緒だと。
これはわかりやすい。 0^..^10 とか。この^を付けた範囲演算子の愛称(?)はNeko operatorらしい。なるほど。


まぁPerl 6の新機能の一部ですね。
配列関係の変更点は結構重要ですよ。特にシジルが変わる件。
まぁしかしこれ以外とは無縁なコードを書いてる人も多いかもね。
あと、おもしろい機能、高次演算子のこと。

my @r=1..10;
say [*] @r;
say [+] (1..100).map( {$_**2} );
my @a=1..100;
my @ra=@a.reverse;
my @apra=@a>>+<<@ra;
( [==] @apra ).perl.say;
say @apra[0]*@apra/2;
(@r>>*<<2).perl.say;

まぁなんじゃこれはという話だが、これは全くの新機能。
[*] @rとしてるが、これは@r[0]*@r[1]* … *@r[@r.end]という計算をしてる。
こういうことをするのが高次演算子です。英語で言うとMeta operator。
Perl 6での階乗計算はこれでOK。スマートですね。
総和も楽チン。mapは引数にブロックを取ります。
{$_**2}とか->$x{$x**2}を引数に書けばOK。これで二乗が並ぶ配列が作れる。
そして総和を[+]で取ると。いや便利便利。
@a>>+<<@raとしてるが、これは(@a[0]+@ra[0] , … , @a[@a.end]+@ra[@a.end])とすること。
長さは長い方に合わせて決まります。足りない分はundefと計算すると。
数学で総和の話が出てきたとき、1から100並べたのと100から1を並べたのを足すと全部101になると。
それを確認するのも簡単。[==]を使えばいいんです。
けどなんか違和感あるよね。@apra[0]==@apra[1]==@apra[2]==…==@apra[@apra.end]って計算できるのか。
実はPerl 6では$x==$y==$z、10<$x<20と書くことができます。
それぞれ、($x==$y)&&($y==$z)、(10<$x)&&($x<20)と書くことと一緒。すごい便利ですね。
というわけで結果は全部等しいから、Bool::Trueと真ですね。
なので、@apra[0]*@apra/2とすれば数学で言ってた通りに総和が計算できた。
めでたしめでたし。という風なことができます。


まぁこんな具合です。
使用価値の高い機能もたくさん増えました。
あと、クラス関係のことと、正規表現関係のことをやりたいもんだが…
いかんせん資料が少ない。
クラス関係は結構変わったらしい。変わりすぎて何がなんだか。
正規表現はPerl 6ではルールという名前になってすごい変わるらしい。
変わりすぎてなんのことやらわからん。
まぁとりあえずPerl 6を試してみたという話です。