関数を作る

この記事はPerl6 Advent Calendar 2011の16日目です。


さて、いわゆる構造化プログラミングでは外せない関数ですが、Perl6では幾つか書き方がありますので紹介しましょう。

sub

Perl5でもおなじみ、subキーワードを用いた関数定義の方法です。Perl5とは違う点として、シグネチャを記述できるようになった事が挙げられます。これはマルチディスパッチと組み合わせる事でとても効果を発揮するのですが、これについては以前の記事を参照してください。

# 普通の関数定義
sub func ($arg) { ... }

# 名前を省略すると無名関数に
sub ($arg) { ... }

# マルチディスパッチする場合はmultiキーワードを付ける
multi sub (Int $arg) { ... }
multi sub (Str $arg) { ... }

pointy block

pointy blockという構文を使う事で、より少ない記述で関数(厳密にはブロック)が定義できます。矢印(->)に続けて引数の定義を書き、そのあとに中括弧で処理するブロックを置きます。

# pointy block
-> $arg { $arg.sqrt }

# 上と大体同じ
{ $_.sqrt }

# 更に省略
{ .sqrt }

placeholder variable

11/12/18追記

ブロックの中にハット(^)から始まる変数を宣言する事で、渡した引数が出現した順変数名の辞書順に格納されていきます。

{ $^a - $^b }(1,2)
#> -1

WhateverCode

placeholderと似ていますが、変数ではなくアスタリスク(*)を置く事で、渡した引数がアスタリスクと置き換えられます。

(*.sqrt).WHAT
#> WhateverCode()
(*.sqrt).(4)
#> 2

WhateverCodeは中括弧が必要無いため、mapなどに渡すブロックを作る時に役立ちます。

(1,2,3,4,5).map(*.sin);
#> 0.841470984807897 0.909297426825682 0.141120008059867 -0.756802495307928 -0.958924274663138

# 普通に書くとこんな感じ?
(1,2,3,4,5).map({$_.sin});

まとめ

詳しく仕様を見ていくと色々違いはあるのですが、Perl6にはこのように様々な関数定義の構文が用意されています。