読者です 読者をやめる 読者になる 読者になる

eachbox

APL/J言語

Math for the Layman by Kenneth Iverson
を読んでいて、11章のGuessing gamesというところの1題目にeachboxというのが出てきます。

   a=: 3 4
   i. a
0 1  2  3
4 5  6  7
8 9 10 11
   i.3
0 1 2
   i.4
0 1 2 3
   eachbox=: &.>
   i. eachbox a
 +-----+-------+
 |0 1 2|0 1 2 3|
 +-----+-------+

はじめわからなかったのでいろいろいじくっていました。
わかっただけでなく発見もありましたので、書いてみます。


まず、上の例の説明をします。アイドット(i.)という動詞は数列やマトリックスを作る便利な動詞です。
数字が一つだと数列を作り、数字が複数だとマトリックス(行列)や、もっと高次の配列がいとも簡単にできます。
上の例では複数の数のそれぞれに動詞を作用させて結果をボックス化するために、eachboxという副詞を作っていて、その例としてアイドット(i.)を使っています。その結果、アイドット(i.)を3と4それぞれに作用させた結果がそれぞれのボックスに入っています。
eachboxに使われているアンドドット(&.)は動詞の間にはさまれると、右側引数に右側動詞を作用させ、その結果に左側動詞を作用させ、さらにその結果に右側動詞の逆関数を作用させるというややこしい作用をします。


今回の場合だと、大なり記号(>)はボックス解除の動詞ですので、その逆関数はボックス化ということになります。つまり小なり記号(<)です。右側引数がボックスに入っていた場合、ボックスを解除して、左側動詞を作用させて、その結果をボックスに入れます。今回の場合、aは3 4という数列ですので、そのまま順番にアイドット(i.)に与えられて、結果をボックス化したものが全体の結果になっています。


つぎに実験です。


別の方法で同じ結果を出すことができるか。

   i.eachbox a
 +-----+-------+
 |0 1 2|0 1 2 3|
 +-----+-------+
   (i.3);(i.4)
 +-----+-------+
 |0 1 2|0 1 2 3|
 +-----+-------+
   i."0 a
0 1 2 0
0 1 2 3
   <@i."0 a
 +-----+-------+
 |0 1 2|0 1 2 3|
 +-----+-------+
   <@i.@> a
 +-----+-------+
 |0 1 2|0 1 2 3|
 +-----+-------+

というように、今回の場合ではeachboxという副詞をつくらなくても目的の結果は得られます。
ところが、右側引数がボックスの場合、とても役に立ちます。

   c=: i.eachbox a
   c
 +-----+-------+
 |0 1 2|0 1 2 3|
 +-----+-------+
   *:eachbox c
 +-----+-------+
 |0 1 4|0 1 4 9|
 +-----+-------+
   *:"0 c
 |domain error
 |       *:"0 c
   <@*:@> c
 +-+-+-+-+
 |0|1|4| |
 +-+-+-+-+
 |0|1|4|9|
 +-+-+-+-+

ボックスのそれぞれの内容に何かの作用をさせたい場合、なかなか他の方法ではうまくいかないのが、アンドドットと大なり記号を使ったやりかたで簡単に目的を達成できます。ボックスが行列になっていても問題ありません。

   ]d=:2 2$(1 2);(3 4);(5 6);(7 8)
 +---+---+
 |1 2|3 4|
 +---+---+
 |5 6|7 8|
 +---+---+
   *: eachbox d
 +-----+-----+
 |1 4  |9 16 |
 +-----+-----+
 |25 36|49 64|
 +-----+-----+


以上