if文なしでじゃんけん というのを見たので J 言語でも書いてみました。
J の if 文
J 言語というと、+/>:i.100
1 のような記号の羅列でプログラムを書けることで有名 (?) ですが、手続き的な記述も可能です。
if. a do.
echo'true'
else.
echo'false'
end.
とはいえ、じゃんけん程度の簡単な場合分けなら if 文よりも配列を使って分岐することが多いように思います 2。そこで、if 文に加えて配列を利用した分岐も禁止することにしました。
下準備
実装に使う部品を用意します。可読性を高めるために、処理を細かく分割しています 3。もちろん、ここでも if などの条件分岐は使っていません。
is=: 0 0 $ {{ (x)=: y }}
rps=: (< [ is~);._1' rock paper scissors'
vs=: ,
sign=: {{ {.m }}
beats=: {{
(x vs x) is 'あいこ'
(x vs y) is 'あなたの勝ち'
(y vs x) is 'あなたの負け'
}}
result=: {{
'[' , (".x sign) , ' vs ' , (".y sign) , '] ' , ".x vs y
}}
every=: {{ u@v&>/~ }}
of=: ]
実装
上で定義した部品を組み合わせると、簡潔に実装することができます。
rock sign is '✊'
paper sign is '🖐'
scissors sign is '✌'
rock beats scissors
paper beats rock
scissors beats paper
echo every result of rps
[✊ vs ✊] あいこ
[✊ vs 🖐] あなたの負け
[✊ vs ✌] あなたの勝ち
[🖐 vs ✊] あなたの勝ち
[🖐 vs 🖐] あいこ
[🖐 vs ✌] あなたの負け
[✌ vs ✊] あなたの負け
[✌ vs 🖐] あなたの勝ち
[✌ vs ✌] あいこ
宣言的で、とても可読性が高いですね。ソースコードが そのままドキュメントとしても機能しています 4。J 言語の構文には柔軟性があるので、このように小さな DSL をアドホックに作って使用することができます。
場合分けは、変数名を動的に生成して eval することによって実現しています (beats
・result
辺り)。詳しい説明を書く気力は残っていないので、知りたい方は最新版の J をインストール して試してみてください (丸投げ 5
コード全体
is=: 0 0 $ {{ (x) =: y }}
rps=: (< [ is~);._1' rock paper scissors'
vs=: ,
sign=: {{ {.m }}
beats=: {{
(x vs x) is 'あいこ'
(x vs y) is 'あなたの勝ち'
(y vs x) is 'あなたの負け'
}}
result=: {{
'[' , (".x sign) , ' vs ' , (".y sign) , '] ' , ".x vs y
}}
every=: {{ u@v&>/~ }}
of=: ]
rock sign is '✊'
paper sign is '🖐'
scissors sign is '✌'
rock beats scissors
paper beats rock
scissors beats paper
echo every result of rps
余談 (と布教)
ちなみに、上のプログラムでは if 文だけでなく for / while 文も使わずに全てのパターンを列挙しています。これには配列を処理する機能の一つ /
を使っています。J では九九の表も同様の方法で簡単に作れます。
*/~>:i.9
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40 45
6 12 18 24 30 36 42 48 54
7 14 21 28 35 42 49 56 63
8 16 24 32 40 48 56 64 72
9 18 27 36 45 54 63 72 81
この記事を読んで少しでも J に興味を持った方は、是非試してみてください。