たのしいPerl6 その1

こんにちは id:anatofuz です.これは琉大情報工学科(知能情報コース) Advent Calendar 2018 4日目の記事です.

今日は皆さん大好きなPerl6についてです.

Perl6とは

Perl6に関しては僕の卒論を見ていただけると良いかと思います

Perl6とはPerlっぽい別言語です. 誤解されることが多いですがPython2とPython3の関係ではなく,どちらかというとJavaJavascriptっぽい関係です.

当初はPerl5の次期バージョンとして開発されていましたが, 開発が進むに連れて互換性の無さや新規文法がもりもり増えてしまった事で「あれ,これPerlじゃなくね?」という事で別の言語となりました.

Perl6は設計と実装が分離しており,主要な実装はRakudoです. 現在の設計はテストスイートRoastを,実装に関してはドキュメントを見るという世界です.

ちなみにRakudoの由来は駱駝道 ( 🐫道) です.なぜ🐫かというとPerlのマスコットキャラがラクダであるからだと思います.

現在はもはやPerl6から別名にしようという動きが一部であり,「6lang」にしようという流れを得て,現在は「Raku」という別名がついています.

Perl6の入れ方

実はPerl6はPythonやPerl5の様に 「perl6っていうコマンドが一つある」 訳ではありません.

実はPerl6を実行するコマンドperl6はシェルスクリプトで.実態はmoarというバイナリにライブラリパスなどを設定して実行しているものです.

これはPerl6がNQPと呼ばれるサブセットで書かれており, このNQPをMoarVMやJVMが解釈するという構成になっている為です. つまり実際に動かすのはperl6ではなくMoarVMのバイナリmoarです. ではPerl6をinstallする際には,この辺を個別でインストール必要があるのでしょうか.

実はそんなことも無く,rakudo-starというPerl6に必要なものをひとまとめにしたツールが配布されています.

(ちなみに rakudo-starのstarはシェルなどのワイルドカード* を使ったrakudo-* の意味です)

Macの場合

macの場合は二種類あり,公式からdmgをdlしてパスを通す 方法か, brewで入れる方法があります.

brewの場合は

$ brew install rakudo-star

これで入ります.

Perl6で遊ぼう

では試しにPerl6のREPLで遊んでみましょう. Perl5とは違い, Perl6はデフォルトでperl6と打つとREPLモードになります.

$perl6
To exit type 'exit' or '^D'

落ち着いて素数を数えよう

実はPerl6には遅延評価があり,しかも数学の無限大を示すInfクラスがあります. これを組み合わせると如何のようにな配列を作れます.

> my @primes = (^∞).grep: *.is-prime;
[...]

これは ^ がrangeクラスのコンストラクタで,0から^ の右の値未満の範囲を作るという意味です.つまり0から無限大のクラスです.

これにメソッドチェーンでgrepをつなげます.grepは配列からある条件を満たす要素を出すものです.

この *.is-prime は,その中の要素が is-prime つまり素数であるならば真を返します.

そして返り値を受け取る my @primes はPerl5と同じく配列の宣言です.

> の次はPerl6のREPLが返した値ですが [...] とありますが,これは配列だが中身はまだ計算してないということです.

本当に素数が入っているか見てみましょう. Perl6で配列の要素を参照するには @array[0] などとします. これを出力するには,メソッドチェーンでsayを繋げます.

> @primes[0].say
2
> @primes[1].say
3
> @primes[2].say
5
> @primes[3].say
7
> @primes[4].say
11
> @primes[5].say
13

素数が入ってそうですね!!!

FizzBuzz

FizzBuzzはいろいろな書き方がありますがtitsukiさんの以下のページが面白いです.

qiita.com

特に面白いのが,Perl6は漸進的型付言語と呼ばれる特徴があり,型が無いようにも有るようにも振る舞う事が可能です.

その特徴を活かすと次のようなfizzbuzzがかけます

my subset Fizz of Int where * %% 3;
my subset Buzz of Int where * %% 5;
my subset FizzBuzz of Int where Fizz&Buzz;
my subset OtherNumber of Int where none Fizz|Buzz;

proto sub fizzbuzz ($) { * }
multi sub fizzbuzz (FizzBuzz) { "FuzzBuzz" }
multi sub fizzbuzz (Fizz) { "Fizz" }
multi sub fizzbuzz (Buzz) { "Buzz" }
multi sub fizzbuzz (OtherNumber $number) { $number }

fizzbuzz($_).say for 1..15;

これはsubsetでFizzの型,Buzzの型,FizzBuzzの型,それ以外の型を定義します. multi で関数に引数の型と応じた関数の内容を記述する事が出来,今回はそれを使って型でfizzbuzzをしています.面白いですね.

という訳でPerl6の話でした.結構面白いと思うのでぜひ遊んでみてはいかがでしょうか.