pockestrap

Programmer's memo

次のRubyプログラムの出力はなにか。

元ネタ: 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節でpqにそれぞれ1と2を代入し、その結果が真に評価されてp 3p pp qを実行すればそうなると考えるのが自然でしょう。

ですが、これは間違っています。 なぜならばwhen p, q = 1, 2pqへの多重代入ではないからです。

この,は多重代入ではなく、whenに複数の条件を指定したものと解釈されています。 わかりやすいようにカッコを入れると、when p, (q = 1), 2のようになります。 つまりpq = 12のいずれかが真であればp 3を実行する、という条件になっています。

また、pメソッドは引数なしで実行した場合にはなにも表示せずnilを返します。 そのためq = 1は評価されqに1が代入されます。 そしてp pは、変数pが存在しないためpメソッドの戻り値をpメソッドで表示することになり、つまりp nilと同じ意味になります。


whenで多重代入をしたい気持ちになり、「あれ、ifの条件に多重代入を書いたらSyntax Errorになるけどwhenだとどうなるんだろう?」と思って書いてみたらSyntax Errorにはならず、面白い挙動をしたのでクイズにしてみました。 お楽しみいただけたのなら幸いです。