元ネタ: https://twitter.com/p_ck_/status/1164901123666272262
問題
次のRubyプログラムを実行した時の出力を、次の4つから選べ。
case when p, q = 1, 2 p 3 else p 4 end p p p q
選択肢1
3 1 2
選択肢2
3 nil 1
選択肢3
4 1 2
選択肢4
3 nil 2
答えと解説
空行を空けた上で答えと解説を書きます。 読みたい方はスクロールしてください。 挑戦したい方はスクロールせずに挑戦してください。
答え
正解は選択肢2です。
$ ruby problem.rb 3 nil 1
解説
問題のコードを再掲します。
case when p, q = 1, 2 p 3 else p 4 end p p p q
おそらく、選択肢1の3 1 2を想像した方が多いのではないかと思います。
when節でpとqにそれぞれ1と2を代入し、その結果が真に評価されてp 3とp p、p qを実行すればそうなると考えるのが自然でしょう。
ですが、これは間違っています。
なぜならばwhen p, q = 1, 2はpとqへの多重代入ではないからです。
この,は多重代入ではなく、whenに複数の条件を指定したものと解釈されています。
わかりやすいようにカッコを入れると、when p, (q = 1), 2のようになります。
つまりp、q = 1、2のいずれかが真であればp 3を実行する、という条件になっています。
また、pメソッドは引数なしで実行した場合にはなにも表示せずnilを返します。
そのためq = 1は評価されqに1が代入されます。
そしてp pは、変数pが存在しないためpメソッドの戻り値をpメソッドで表示することになり、つまりp nilと同じ意味になります。
whenで多重代入をしたい気持ちになり、「あれ、ifの条件に多重代入を書いたらSyntax Errorになるけどwhenだとどうなるんだろう?」と思って書いてみたらSyntax Errorにはならず、面白い挙動をしたのでクイズにしてみました。
お楽しみいただけたのなら幸いです。