君はあのコンマ演算子を知っているか?

僕は知らなかったです。

Perlで遭遇

次のようなPerlのコードを読んでいるときに思ってなかった挙動をした。

my $x = ('a', 'b');
$x  # => ??

始め以下のような想定をして $x には 'a' が入るのだと思っていた。

  1. 左辺がスカラコンテキストなので、右辺もスカラコンテキストになる
  2. 配列の区切りの最初の値が入り $x には 'a' が入る
  3. 'b' はどの変数にも入らず捨てられる

しかし実行してみると $x には 'b' が入る。

my $x = ('a', 'b');
$x  # => 'b'

これはどういうことかと思い調べてみると、どうやらコンマ演算子というものがあるらしい。perldocを引いてみると

perldoc.jp

二項演算子の "," はコンマ演算子です。 スカラコンテキストではその左引数を評価し、その値を捨てて、 それから右引数を評価し、その値を返します。 これはちょうど、C のコンマ演算子と同じです。 リストコンテキストでは、これは単にリスト引数の区切り文字で、 双方の引数をそのリストに挿入する働きがあります。 これらの引数も左から右に評価されます。

そんなのあるの……。つまりさっきのコードは以下のような流れで 'b' が入る。

  1. 左辺がスカラコンテキストなので、右辺もスカラコンテキストになる
  2. 'a', 'b',二項演算子コンマ演算子として働く
  3. そのため 'a' を評価し値を捨て、 'b' を評価し値を返す
  4. そして $x には 'b' が入る

という流れ。

恥ずかしながら2年弱Perlを書いててコンマ演算子のことは初めて知った……。あまりこういうコードを書く機会は無いだろうけどミスってこのようなコードを書いてしまった時は意図しないハマりポイントになりそうだなと思った。

ちょっと待てよ……

Perlのハマりポイントを知ったところで、さっきのperldocの文を思い出してみると……。

これはちょうど、C のコンマ演算子と同じです。

ということはC言語やそれ以外の言語にもあるということではないだろうか?そう思って雑にググってみるとWikipediaがヒットした。

コンマ演算子 - Wikipedia

CやC++をめきめき書いたことは無いのでなるほど〜といった感想程度だったけど、次のコード例はちょっと面白い。

int a=1, b=2, c=3, i;   // このコンマは演算子としてではなくセパレータとして作用する
i = (a += 2, a + b);    // aに2を加算した後、a+b = 3+2 をiへ代入する                                    ... a=3, b=2, c=3, i=5

ちょっとしたコード短縮テクニックなのかなと思ったけど、Twitterで調べてみたら定期的にツイートがある。CやC++ということは競技プログラミングの界隈だと普通に知られたテクニックだったりするのだろうか?

コンマ演算子 - Twitter Search

お前もか〜〜

見つけてしまった瞬間「マジかよ……」と思ってしまったのだけれ、JavaScriptにもコンマ演算子は存在していた。雰囲気は同じ感じで詳細はMDNを見ればよさそう。

developer.mozilla.org

Minifierとかでコードが圧縮された後だとこんな感じのコードが生成されているのかもしれないなと思った。

終わりに

知らない演算子を発見するの結構新鮮な気分だった。PerlJavaScriptも仕事で書いているけど、言語の仕様を上から下までさらって覚えるということはしたことないので他にもこういった発見は今後もあるんだろうなと思った。 (あとJavaScriptオチ担当として優秀な気がする)