次の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
節で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にはならず、面白い挙動をしたのでクイズにしてみました。
お楽しみいただけたのなら幸いです。