Perl 6の公開練習のコーナー、今回は真偽値(Boolean value)についてです。

 Perl 5では、真になる式は1、偽になる式は空文字列を返します。
#! /usr/local/bin/perl
# compar_1.pl -- Perl 5で真偽値の練習

use strict;
use warnings;
use 5.10.0;

say "2 + 3 == 5【", 2 + 3 == 5, "】";
say "2 * 3 == 5【", 2 * 3 == 5, "】";

[sample]$ ./compar_1.pl
2 + 3 == 5【1】
2 * 3 == 5【】
[sample]$

 Perl 6で同じことをやるとどうなるでしょうか。

#! /usr/bin/env perl6
# compar_1.p6 -- Perl 6で真偽値の練習

"2 + 3 == 5【{ 2 + 3 == 5 }】".say;
"2 * 3 == 5【{ 2 * 3 == 5 }】".say;

 いちおうオブジェクト指向的にsayを後付けにし、二重引用符の中にブレース{}で囲んでPerlのプログラムを書ける機能を使ってみました。

[sample]$ ./compar_1.p6
2 + 3 == 5【True】
2 * 3 == 5【False】
[sample]$

 へぇー!
 Perl 6ではTrueまたはFalseというBool型の定数があり、それが表示されました。

 さて、比較演算子のうち、以下のものは5も6も同じです。
 ただし1を返していた時にTrueを、0を返していた時にFalseを返すだけです。

eq、ge、gt、le、lt、ne、==、>=、>、<=、<、!=

 <=>(宇宙船演算子)も機能としては一緒ですが、戻り値が変わりました。Perl 5では左が小さければ-1、等しければ0、大きければ1を返していました。

#! /usr/local/bin/perl
# compar_2.pl -- Perl 5で真偽値の練習2(宇宙船演算子)

use strict;
use warnings;
use 5.10.0;

say "2 <=> 3【", 2 <=> 3, "】";
say "3 <=> 3【", 3 <=> 3, "】";
say "3 <=> 2【", 3 <=> 2, "】";

[sample]$ ./compar_2.pl
2 <=> 3【-1】
3 <=> 3【0】
3 <=> 2【1】
[sample]$

 これをPerl 6に移植します。

#! /usr/bin/env perl6
# compar_2.p6 -- Perl 6で真偽値の練習2(宇宙船演算子)

"2 <=> 3【{ 2 <=> 3 }】".say;
"3 <=> 3【{ 3 <=> 3 }】".say;
"3 <=> 2【{ 3 <=> 2 }】".say;

[sample]$ ./compar_2.p6
2 <=> 3 【Less】
3 <=> 3 【Same】
3 <=> 2 【More】
[sample]$

 なんとLess、Same、Moreという値を返すようになりました。分かりやす過ぎて気持ち悪い!

 次はcmp(文字列として比較を行う<=>)です。まずはPerl 5。

#! /usr/local/bin/perl
# compar_3.pl -- Perl 5で真偽値の練習2(cmp演算子)

use strict;
use warnings;
use 5.10.0;

say "\"dog\" cmp \"dot\【", "dog" cmp "dot", "】";
say "\"dog\" cmp \"dog\【", "dog" cmp "dog", "】";
say "\"dot\" cmp \"dog\【", "dot" cmp "dog", "】";

[sample]$ ./compar_3.pl
"dog" cmp "dot【-1】
"dog" cmp "dog【0】
"dot" cmp "dog【1】

 これがlegという演算子に変わりました。less than、equal、greater thanの略だそうです。


#! /usr/bin/env perl6
# compar_3.p6 -- Perl 5で真偽値の練習3(leg演算子)

"\"dog\" leg \"dot\"【{ "dog" leg "dot" }】".say;
"\"dog\" leg \"dog\"【{ "dog" leg "dog" }】".say;
"\"dot\" leg \"dog\"【{ "dot" leg "dog" }】".say;

[sample]$ ./compar_3.p6
"dog" leg "dot"【Less】
"dog" leg "dog"【Same】
"dot" leg "dog"【More】

 で、cmpはなくなったのかというと、「スマートな」三値比較演算子というものに置き換わりました。
 数値vs.数値だと数値としての比較(<=>)を行います。
 文字列vs.数値、数値vs.文字列、文字列vs.文字列だと文字列としての比較(leg)を行います。どうもそうらしいです。

#! /usr/bin/env perl6
# compar_4.p6 -- Perl 6で真偽値の練習4(cmp演算子)

"2.0 cmp 3【{ 2.0 cmp 3 }】".say;
"3.0 cmp 3【{ 3 cmp 3 }】".say;
"3 cmp 2.0【{ 3 cmp 2 }】".say;

"\"dog\" cmp \"dot\"【{ "dog" cmp "dot" }】".say;
"\"dog\" cmp \"dog\"【{ "dog" cmp "dog" }】".say;
"\"dot\" cmp \"dog\"【{ "dot" cmp "dog" }】".say;

"\"2.0\" cmp 2【{ "2.0" cmp 2 }】".say;
"\"2.0\" cmp \"2.0\"【{ "2.0" cmp "2.0" }】".say;
"2 cmp \"2.0\"【{ 2 cmp "2.0" }】".say;

[sample]$ ./compar_4.p6
2.0 cmp 3【Less】
3.0 cmp 3【Same】
3 cmp 2.0【More】
"dog" cmp "dot"【Less】
"dog" cmp "dog"【Same】
"dot" cmp "dog"【More】
"2.0" cmp 2【More】
"2.0" cmp "2.0"【Same】
2 cmp "2.0"【Less】

 へぇー。

 さて、True、FalseはBool型の変数と気軽に言ってしまいました。
 Bool型は、Int型、String型、Rat型(有理数)、Real型、Complex型、Any型(なんでも入る、デフォルト)と同じく、変数の宣言に使える型です。

 以下のコードを見てください。

#! /usr/bin/env perl6
# compar_5.p6 -- Perl 6で真偽値の練習5(Bool演算子)

my Bool $true = ( 3 == 3 );

if $true {
 say "True 1";
} else {
 say "False 2";
}

if False {
 say "True 1";
} else {
 say "False 2";
}

say "\$true is { $true.perl }";
say "True is { True.perl }";
say "Same is { Same.perl }";
say "3 <=> 4 is { 3 <=> 4 } and it is { ( 3 <=> 4 ).perl }";

[sample]$ ./compar_5.p6
True 1
False 2
$true is Bool::True
True is Bool::True
Same is Order::Same
3 <=> 4 is Less and it is Order::Less

 まず、Perl 6ではifのあとの条件にカッコ()がいらなくなりました! これは見やすいですね。

 次に、if True { ... } と書いています。これはPerl 5のif (1) { ... }と一緒で、必ずブロック内が実行されます。たとえば while True { ... } と書けば無限ループになります。これはPerl 6の while (1) { ... }よりも断然見やすいと思います。

 次に$true.perlのperlはPerl 5時代のData::Dumplerに当たるメソッドで、作用対象が何であるか(形と値)を分かりやすく表示してくれます。実行してみます。

 $trueはBool型の変数でTrueが入っています。
 定数Trueは型で、やはりTrueが入っています。
 ここまでは当たり前。

 次に宇宙船演算子が返すLess、Same、Moreが何型か調べてみましたら、Order型だそうです。
 へぇ〜。