perl6をインストールした後cat.plをcat.p6に書き換える

リリースされてそろそろ一年。

使ってみないとperl6のことがわからないので使ってみる。

まずは一番単純なcatコマンドのように動くコマンド作りから。

rakudo & panda インストール

rakudobrewというPerlBrewのようなスクリプトでインストール。簡単。

How to get Rakudo Perl 6 | rakudo.org

ドキュメントをインストール

そもそもperl6の書き方がわからない。

webで調べてもいいのですが、perldocを重宝していたので同じものが無いかと調べてみると p6doc というものがあったのでインストール。

$ panda install p6doc

自分の環境では libssl-dev の追加が必要だった。

また、p6docコマンドがPATHの通ったところに置かれなかったので調整した。

さらに、使っていると以下のコマンドの実行を勧められたので実行した。

$ p6doc-index build

cat.plからcat.p6へ

cat.pl

cat.plの挙動は以下を想定している。

$ cat helloworld
Hello
World

$ ./cat.pl helloworld
Hello
World

$ cat helloworld | ./cat.pl
Hello
World

実装は以下の通り。

#!/usr/bin/env perl

use strict;
use warnings;

while (<>) {
    print;
}

cat.p6

先に結果を載せておく。

#!/usr/bin/env perl6

use strict;

for (lines) {
    .say;
}

try & error

perl6で実行

cat.plをperl6で実行するよう書き換え。

#!/usr/bin/env perl6

use strict;
use warnings;

while (<>) {
    print;
}

実行すると以下のエラーが出る。

$ ./cat.pl helloworld 
===SORRY!===
Could not find warnings at line 4 in:
    /home/ajishixo/.perl6
    /home/ajishixo/.rakudobrew/moar-nom/install/share/perl6/site
    /home/ajishixo/.rakudobrew/moar-nom/install/share/perl6/vendor
    /home/ajishixo/.rakudobrew/moar-nom/install/share/perl6
    CompUnit::Repository::AbsolutePath<189992464>
    CompUnit::Repository::NQP<191589208>
    CompUnit::Repository::Perl5<191589232>

warningsプラグマは無くなった様子。

use warnings を削る

#!/usr/bin/env perl6

use strict;

while (<>) {
    print;
}

実行した結果

$ ./cat.pl helloworld 
===SORRY!=== Error while compiling /home/ajishixo/dev/perl6/./cat.pl
Unsupported use of <>; in Perl 6 please use lines() to read input, ('') to represent a null string or () to represent an empty list
at /home/ajishixo/dev/perl6/./cat.pl:5
------> while (<⏏>) {

ダイアモンド演算子も無くなった様子。

ダイアモンド演算子をlinesに書き換え

#!/usr/bin/env perl6

use strict;

while (lines) {
    print;
}
$ ./cat.pl helloworld 
===SORRY!=== Error while compiling /home/ajishixo/dev/perl6/./cat.pl
Unsupported use of bare "print"; in Perl 6 please use .print if you meant $_, or use an explicit invocant or argument, or use &print to refer to the function as a noun
at /home/ajishixo/dev/perl6/./cat.pl:6
------>       print⏏;

print;print $_;$_を省略した形でしたが、$_.print;として$_を省略し.printという形になるのですね。

printを.printに書き換え

#!/usr/bin/env perl6

use strict;

while (lines) {
    .print;
}

実行すると

$ ./cat.pl helloworld 
Use of uninitialized value of type Any in string context.
Methods .^name, .perl, .gist, or .say can be used to stringify it to something meaningful.
  in block <unit> at ./cat.pl line 6
Use of uninitialized value of type Any in string context.
Methods .^name, .perl, .gist, or .say can be used to stringify it to something meaningful.
  in block <unit> at ./cat.pl line 6

stringのコンテキストでAny型の初期化されていない値が使われているとのこと。 Any型とはなんぞや、ということで先ほど入れたp6docに尋ねてみる。が、イマイチ分からず。。 .sayの使用をすすめられたので書き換える。

printをsayに書き換え

#!/usr/bin/env perl6

use strict;

while (lines) {
    .say;
}

実行すると

$ ./cat.pl helloworld 
(Any)
(Any)

またもAny。。

linesの戻り値が気になるのでp6docに尋ねてみる。

$ p6doc -f lines
We have multiple matches for 'lines'

        Type::Cool.lines Type::Str.lines
        Type::Supply.lines Type::IO::Handle.lines Type::IO::Socket::INET.lines

今回はファイルの読み込みなので Type::IO::Handle.lines を選ぶ。

$ p6doc -f Type::IO::Handle.lines
  method lines

    method lines($limit = Inf)

Return a lazy list of the file's lines read via get, limited to $limit
lines. The new line separator (i.e., $*IN.nl-in) will be excluded.

    my @data; 
     my $data-file = open 'readings.csv'; 
     for $data-file.lines -> $line { 
         @data.push($line.split(',')) 
     } 
    

分からん。

紆余曲折し、以下の記述にたどり着く。

$ p6doc variables
// 略
Calling a method on $_ can be shortened by leaving off the variable name:

    .say;                   # same as $_.say

m/regex/ and /regex/ regex matches and s/regex/subst/ substitutions work on
$_: 

    say "Looking for strings with non-alphabetic characters...";
    for <ab:c d$e fgh ij*> {
        .say if m/<!alpha>/;
    }

whileをforに書き換え

#!/usr/bin/env perl6

use strict;

for (lines) {
    .say;
}

実行して無事成功。

$ ./cat.pl helloworld 
Hello
World

$ cat helloworld | ./cat.pl
Hello
World

拡張子を変更

$ mv cat.pl cat.p6

おわりに

なぜwhileではダメでforなら良かったのかはp6doc controlを読んでみたけど分からず。

今後の使用で理解していこう。