Shogo's Blog

Dec 5, 2024 - 2 minute read - perl

Perl 5.40に真偽値の排他的論理和を表す新しい演算子が導入されました

この記事は、Perl Advent Calendar 2024 5日目の記事(穴埋め)です。 4日目は@shogo82148で「Perl 5.40でtry/catch機能が安定版になりました」でした。


Perl 5.40.0 から、真偽値の排他的論理和を表す ^^ 演算子が導入されました。

背景

Perl には「コンテキスト(文脈)」と呼ばれる概念があります。 Perlはプログラム内の文脈によって、今扱っているデータをどんな種類(数値なのか文字列なのか)で解釈するかを決定します。

たとえば $x + $y は数値加算の演算子であり、$x$y は数値コンテキストで解釈されます。 数値コンテキストではデータは数値として評価されます。 もし $x$y に文字列が入っていた場合は、一度数値に変換してから演算が行われます。

そして、Perlにはコンテキスト毎に異なった演算子が存在します。 たとえば、「論理積」を表す演算子の場合、 「整数の論理積」「文字列の論理積」「真偽値の論理積(優先度高)」「真偽値の論理積(優先度低)」の4種類の演算子があります。 「論理和」や「排他的論理和」を加えて表にまとめてみると以下のようになります。

コンテキスト 論理積 論理和 排他的論理和
数値 & | ^
文字列 &. |. ^.
真偽値(優先度高) && ||
真偽値(優先度低) and or xor

さて、この表をよく見ると「真偽値の排他的論理和」の部分にひとつだけ空白があります。 「この空白を埋めよう!」というモチベーションで追加されたのが ^^ 演算子です。 ^^ は両辺の真偽値コンテキストで評価し、その排他的論理和を計算します。

試してみた

実際に試してみました。

use v5.40;

sub say_bool($v) {
    say $v ? "true" : "false";
}

say_bool false ^^ false;
say_bool false ^^  true;
say_bool  true ^^ false;
say_bool  true ^^  true;

Perl 5.40 で実行してみると、真理値表通りの結果が得られましたね。

false
true
true
false

xor演算子との違いは?

xor 演算子と ^^ 演算子の違いは優先順位です。

たとえば以下のコードは (say_bool false) xor false; と解釈されてしまって、 期待したとおりには動きません。

use v5.40;

sub say_bool($v) {
    say $v ? "true" : "false";
}

say_bool false xor false;
say_bool false xor  true;
say_bool  true xor false;
say_bool  true xor  true;
Useless use of logical xor in void context at xor-legacy.pl line 7.
Useless use of logical xor in void context at xor-legacy.pl line 8.
Useless use of logical xor in void context at xor-legacy.pl line 9.
Useless use of logical xor in void context at xor-legacy.pl line 10.
false
false
true
true

正しく動作させるにはカッコを補う必要があります。

use v5.40;

sub say_bool($v) {
    say $v ? "true" : "false";
}

say_bool(false xor false);
say_bool(false xor  true);
say_bool( true xor false);
say_bool( true xor  true);

短絡評価(ショートサーキット)は機能するの?

排他的論理和に短絡評価(ショートサーキット)は機能するのでしょうか? 先に結論を書いておくとしません。

論理積、論理和の演算子は短絡評価をします。 たとえば、以下のコードで関数 g は評価されず、実行されません。

say_bool false && g();

&& の左被演算子が false なので、右被演算子を評価するまでもなく、結果が false だとわかるからです。

排他的論理和(^^)の場合はどうでしょう? 簡単なプログラムを書いて検証してみました。

use 5.40.0;
use utf8;
use Encode;

sub say_bool($v) {
    say $v ? "true" : "false";
}

sub f($v) {
    say encode_utf8("fが評価されました");
    return $v;
}

sub g($v) {
    say encode_utf8("gが評価されました");
    return $v;
}

say_bool f(false) ^^ g(false);
say_bool f(false) ^^ g( true);
say_bool f( true) ^^ g(false);
say_bool f( true) ^^ g( true);

実行してみると、毎回すべての被演算子が評価されている様子を確認できます。

fが評価されました
gが評価されました
false
fが評価されました
gが評価されました
true
fが評価されました
gが評価されました
true
fが評価されました
gが評価されました
false

左被演算子の情報だけでは最終結果が決定しないので、このような結果になるんですね。

まとめ

Perl 5.40.0 から、真偽値の排他的論理和を表す ^^ 演算子が導入されました。 &&, || の排他的論理和バージョンで、優先度の高い xor 演算子として動作します。 実際有用な場面が思いつかない。

Perlの世界に新たな光、
XOR ^^が登場するよ、
論理は明確、日々の道、
コードを簡潔にするための手助け。
一つの真実、二つの心、
^^でコードはきれいに整う。
🐇✨

by CodeRabbit


明日6日目は@MacOlinで「JSON::PPのencodeメソッドと日本語とutf8」です。 お楽しみに!

参考