J言語 基礎最速マスター

Project Eulerなどで妙に人気がある言語で前々から気になっていたので,勉強がてら書いてみる.
まだ誰も書いてないみたいだし.
他の言語については(基礎|変態)文法最速マスターシリーズのまととかを見てください.

※初心者なので間違え注意.指摘をお願いします.




J言語はAPLの後継で配列処理の強力な言語.
ASCIIコードの1,2文字で膨大な演算子が定義されている上,
前置記法と後置記法で意味が異なるため可読性に乏しいが複雑な演算を短く書ける.
ジョーク言語ではないが,属性は3(書けるし実行できるが読めない)


基本事項

実行方法

ここからダウンロード,インストールし,jconsoleを起動.
javaのコンソールを立ち上げないように注意が必要.

print文

quoteで囲む

'Hello World!'
コメント文

NB. の後に書く.

'Hello World!' NB. comment

数値

基本事項
  • _ (後に数を書いた場合)負号
  • _ (単独で)無限大
  • __ 負の無限大
  • e 指数
   1e3
1000
   2r3 NB. 2/3
2r3
   1j2 NB. 1+2i
1j2
四則演算

演算子は2項演算子の場合と単項演算子の場合で意味が異なる.
演算子のことをJ言語では動詞というみたいですが,あえて無視する.)

二項演算としての場合

  • + 足し算
   1+1
  • - 引き算
   3-1
2
   2-3
_1
  • * 掛け算
   2*3
6
  • % 割り算(スラッシュでないことに注意)
   6%2
3
   2%3
0.666667

演算子はすべて右結合であることに注意

   1%1+1
0.5

単項演算子としては次のようになります

   + 1
1
   + 1j1
1j_1
  • - 負号反転
   - 2
_2
   - _2
2
   - 2j3
_2j_3
  • * 符号(絶対値を1にする)
   *2
1
   *_3
_1
   *0
0
   *3j4
0.6j0.8
  • % 逆数
   %2
0.5

真偽値

1で真,0で偽を表す.

演算
  • +. or
  • *. and
  • +: nor
  • *: nand
  • -. not
比較

二項演算として

  • = 等号
  • < 小なり
  • > 大なり
  • >: 大なりイコール
   0 = 0
1
   'a' = 'a'
1
   2 < 3
1
   2 < 2
0
   2 <: 2
1
   0 = '0'
0

配列

空白区切りで数字を並べると配列になる.

   1 2 3
1 2 3
配列演算
  • # (単項演算子として)配列の長さを求める
   # 1 1 1
3
  • {. head
   {. 1 2 3
1
  • {: last
   {: 1 2 3
3
  • }. tail
   }. 1 2 3
2 3
  • }: init
   }: 1 2 3
1 2
  • { (2項演算子として)配列のi番目の要素を取り出す(0オリジン)
   0 { 1 2 3
1
   1 { 1 2 3
2
   3 { 1 2 3
|index error
|   3    {1 2 3
   0 1 0 { 1 2 3
1 2 1
  • } 配列のi番目の要素をkにする
   2 (3}) 1 1 1 1 1 1
1 1 1 2 1 1
   2 (1 3}) 1 1 1 1 1 1
1 2 1 2 1 1
  2 4 (1 3}) 1 1 1 1 1 1
1 2 1 4 1 1
  • , 配列の結合
   1 2 3 , 4 5 6
1 2 3 4 5 6
  • 素数がおなじ配列を二項演算でつなぐと,対応する要素同士に演算を施した配列が返ってくる.

HaskellでいうzipWithみたいなもの)

   1 2 3 + 4 5 6
5 7 9
  • 少なくとも一方の配列の要素数が1つの配列を2項演算でつなぐと,要素数が1の配列の要素をもう一方の各配列の要素に作用させる
   1 + 1 2 3
2 3 4
  • 単項演算を配列に作用させると,配列の各要素に作用される
   - 1 2 3
_1 _2 _3
   + / 1 2 3
6
  • i.n 0からn-1までの整数の配列を作る
   i.10
0 1 2 3 4 5 6 7 8 9
  • テーブル(行列)をつくる
   2 2 2 $ i.8
0 1
2 3

4 5
6 7

こうも書ける

   i. 2 2 2
0 1
2 3

4 5
6 7

演算子の合成

演算子を続けて書いたとき,演算順序が特殊になる.

部分適用,単純な合成

m&v yはm v yであることを利用する

(^&3) i.10 NB. 各要素の3乗
0 1 8 27 64 125 216 343 512 729
(>&4) i.10 NB. 各要素は4より大きいか
0 0 0 0 0 1 1 1 1 1
( (*&2) & (^&2) ) i.10 NB. 各要素を2乗して2倍
0 2 8 18 32 50 72 98 128 162

フック

x,yを引数, f,gを演算子とするとき,

(f g) y => y f (g y)
x (f g) y => x f (g y)

のように計算される.

   (- -) 1  NB. 1 - (-1)=2
2
   2 (* *) 3 NB. 2 * (*3) = 2 * 1 = 2
2
フォーク

x,yを引数,f,g,hを演算子とするとき,

(f g h) y => (f y) g (h y)
x (f g h) y => (x f y) g (x h y)

のように計算される.

   (+/ % #)  2 4 9   NB.  (+/ % #) 2 4 9 = (+/ 2 4 9) % (# 2 4 9) = 15 % 3 = 5 (つまり平均)
5
トレイン

e f g h は (e (f g h)) の意味((f g h)のフォークとeをフック)

以下同様に

(a_1 a_2 a_3 ... a_{2n}) => フック (a_1 (a_2 a_3 ... a_{2n}))
(a_1 a_2 a_3 ... a_{2n-1}) => フォーク (a_1 a_2 (a_3 ... a_{2n-1}))

変数,演算子定義

=.で局所定義,=:で大域定義する.

変数

=.や=:を使うだけ.

   num =: 1
   num+1
2
   num=:num+1
   num
2
   
   a,(a=.1 2 3)
1 2 3 1 2 3
演算子定義ー暗黙の定義

暗黙の定義は単項演算子なのか2項演算子なのかを明示せずに定義する方法.
point freeとなるので簡潔で読みにくいものになる

   num=:2
   num*num
4

   plus=:+
   1 plus 1
2

   mean=:+/ % #
   mean i.10
4.5
演算子定義ー明示的な定義

単項演算子なのか2項演算子なのかを明示して定義する方法.
演算子の場合,左の引数がx,右の引数がyで予約されている.

:の左で種類を指定し,右に文字列で定義を行う.
3は単項演算子,4は2項演算子

   inc=: 3 : 'y+1'
   inc 2
3

   plus =: 4 : 'x+y'
   1 plus 1
2


:の右に0を置くと複数行で定義ができる.)で定義を終了.
この場合は文字列は使わず定義する.

   plus =: 4 : 0
x+y
)
   2 plus 3
5

制御構文

この辺を使うとJっぽくないような気がする.

if文

Tブロックにはブールが来る(0でないなら真)

  • if文

if. T do. B end.

  • if 〜 else 文

if. T do. B1 else. B2 end.

  • if 〜 elseif文

if. T do. B1 elseif. T1 do. B2 elseif. T2 do. B3 end.

  • 例:階乗
   fact =: 3 : 0
if. y<1 do. 1 else. y*(fact (y-1)) end.
) 
   fact 3
6
   fact 4
24
for文

Tブロックの各要素についてBブロックが評価される.

  • インデックスなし

for. T do. B end.

  • インデックスj

for_j. i.y do. B end.

  • 例:1からyまでの和
      sum =: 3 : 0
s=.0
for_j. i.y do. s=.s+j+1 end.
)
continue, break, return

普通に使える.

具体例

1000以下の3か5で割りきれる数の和

まずは,適当に

   +/(*((0&=)&(5&|)+.((0&=)&(3&|)))) i.1000
233168

(0&=)&(3&|)が3で割り切れるか,
(0&=)&(5&|)が5で割りきれるかを表す.
+.はブールとしてのor
これらをフォークで合成し,3か5で割りきれるか

+/で和をとる.


少し短くしてみる

 +/((*=&0)5&|*3&|)i.1000

4両列車

参考文献

まだまだ紹介しきれなかった機能はたくさんあります.
さらなる情報を欲しい方は下の文献を参考に.