これはMoritz Lenz氏のWebサイトPerlgeek.deで公開されているブログ記事"Perl 5 to 6" Lesson 08 - Junctionsの日本語訳です。
原文はCreative Commons Attribution 3.0 Germanyに基づいて公開されています。
本エントリにはCreative Commons Attribution 3.0 Unportedを適用します。
Original text: Copyright© 2008-2010 Moritz Lenz
Japanese translation: Copyright© 2011 SATOH Koichi
NAME
"Perl 5 to 6" Lesson 08 - ジャンクション
SYNOPSIS
if $x eq 3|4 {
say '$x is either 3 or 4'
}
say ((2|3|4)+7).perl # (9|10|11)
DESCRIPTION
ジャンクションは順序づけられていない値の重ね合わせです。ジャンクションに対する演算はジャンクションの各要素に対して別々に実行(並列化されるかも知れません)され、その結果は同じ型のジャンクションに組み立てられます。
複数あるジャンクション型は真理値コンテキストで評価されたときのみ違いが出ます。型にはany
、all
、one
、none
があります。
型 中置演算子
any |
one ^
all &
1 | 2 | 3
はany(1..3)
と同じです。
my Junction $weekday = any <Monday Tuesday Wednesday
Thursday Friday Saturday Sunday>
if $day eq $weekday {
say "See you on $day";
}
この例では$day
と'Monday'
、$day
と'Tuesday'
などといった各ペアに対してeq
演算子が呼び出され、その結果は再びany
ジャンクションに格納されます。結果が確定するなりすぐに(この場合どれか1つでも比較が真になったら)残りの比較は中止できます。
ジャンクションは演算子だけでなく、サブルーチンに対しても機能します:
if 2 == sqrt(4 | 9 | 16) {
say "YaY";
}
これを可能にするため、ジャンクションは通常の型階層より(ほんのちょっと)外側に位置しています:
Mu
/ \
/ \
Any Junction
/ | \
All other types
もし引数に取ったジャンクションを捕まえて処理するサブルーチンを書きたいなら、パラメータの方をMu
かJunction
として宣言する必要があります。
sub dump_yaml(Junction $stuff) {
# YAMLがジャンクションを表現できたら良いなあ ;-)
....
}
注意: ジャンクションは時々直感に反するふるまいをします。非ジャンクション型では$a != $b
と!($a == $b)
は常に等しいですが、もし一方の変数がジャンクションだとすると違った結果になることがあります:
my Junction $b = 3 | 2;
my $a = 2;
say "Yes" if $a != $b ; # Yes
say "Yes" if !($a == $b); # 出力なし
2 != 3
は真なので$a != 2|3
も真です。一方$a == $b
という比較は単一の真理値(True)を返し、その否定はFalseです。
MOTIVATION
Perlは自然言語にかなり近くなるよう設計されており、自然言語ではしばしば「もし結果が$this
であるか結果が$that
であるなら」という代わりに「もし結果が$this
か$that
であるなら」のようにいいます。ほとんどのプログラミング言語では前者(を翻訳したもの)だけが許されており、少しぶきっちょな感じがします。
ジャンクションのおかげでPerl6は後者も上手に許可しています。
それ無しにはループが必要になるような大量の比較が非常に簡単に書けるようにもしています。
例として数の配列を思い浮かべ、そのすべての要素が非負であることを知りたいと想像して下さい。 Perl5ではこのようなものを書くことになるでしょう:
# Perl 5コード:
my @items = get_data();
my $all_non_neg = 1;
for (@items){
if ($_ < 0) {
$all_non_neg = 0;
last;
}
}
if ($all_non_neg) { ... }
あるいはたまたまList::MoreUtils
を知っているなら
use List::MoreUtils qw(all);
my @items = get_data;
if (all { $_ >= 0 } @items) { ... }
Perl6では短く、かわいらしいものです:
my @items = get_data();
if all(@items) >= 0 { ... }
コメント
コメントを投稿