Wikipediaによるとフィボナッチ数列は
と定義されています。これは再帰(リカーシブ)による定義で、rubyだとそのまま、
def fib(n) if n <= 0 0 elsif n == 1 1 else fib(n - 1) + fib(n - 2) end end
と表記できますが、あまりJ言語向きの課題ではないのではないでしょうか。そんな気がします。
しかし、Eazy Jの第7章はフィボナッチがテーマです。他の言語と同じようなフローを使ったプログラムの書き方ができることの説明のようですが、それはそれで興味があります。
最後の2つを取る、というのは_2&{.(マイナス2アンド左ブレイスドット)と書けます。そしてthenその結果を足すのですから+/@(_2&{.)(プラススラッシュアトマークマイナス2アンドヒダリブレイスドット)となります。これをひとつの動詞とみなすことができますので、その前に,(カンマ)を置くと、動詞が二つ並んだ形になって、APL/J言語で言うところのフックのような作用で、元の数列にその最後の2つの数字の和がつながったものができます。
fib=:,+/@(_2&{.) fib 2 3 2 3 5
さてJ言語には繰り返しの接続詞(コンジャンクション)があって^:(やまコロン、カレットコロン)これを使ってたとえば10回繰り返します。
fib^:10(0 1) 0 1 1 2 3 5 8 13 21 34 55 89
へんな構文なので、あとでVocabularyで調べておこう。
fibという動詞を定義しないで書くと相当わかりにくい形になります。
(,+/@(_2&{.))^:10(0 1) 0 1 1 2 3 5 8 13 21 34 55 89
次に明示的に関数を定義するような例を2つ挙げます。
Fib=:dyad define r=.y [ i=. 0 while. i<x do. i=.i+1 r=.r, +/_2{.r end. ) 10 Fib 0 1 0 1 1 2 3 5 8 13 21 34 55 89
次の例は通常のプログラムの再帰(リカーシブ)バージョンになります。
Fib=:dyad define if. x>0 do. r=.(x-1)Fib y r=.r,+/_2{.r else. r=.y end. ) 10 Fib 0 1 0 1 1 2 3 5 8 13 21 34 55 89
解説です。xとyは定義の中ではxは左側の引数、yは右側の引数を現します。よく、J言語の説明にx.とかy.と書かれていますが、今の6.02のj言語環境ではドットは不要です。
一方、while. do. end. if. else.は必ずドットが必要です。
定義全体は)(右かっこ)で終了します。
一つ目の例の一行目は一行の途中に[(左ブラケット)があって2つの文を一つに書いています。左ブラケットをこのようなセパレータ代わりに使うのはよくあることです。動詞としての[(左ブラケット)は右側を無視して左側の引数をその値とするという意味です。
Fib=:dyad defineというのはFib=: 4 : 0と同じ意味で、J Primerではこの後者の書き方を勧めています。
Fib=: 3 : 0という書き方もあって、この書き方だと単項動詞(monad)と二項動詞(dyad)の両方を一度に定義することができます。
Fib=: 3 : 0 10 Fib y : r=.y [ i=.0 while. i<x do. i=.i+1 r=.r, +/_2{.r end. ) 10 Fib 0 1 0 1 1 2 3 5 8 13 21 34 55 89
定義の途中にある:(コロン)の前が単項動詞の定義で、そこで単項動詞としては左側引数がデフォルトで10の二項動詞となるということが書かれています。
以上