明示的定義の例
ファイルに関数定義を 書くときは関数名に=:を用いなければならない。
grobal定義は 関数の枠を超えるので定義名が衝突すると後者優先になる。
しかし、明示的定義のデバックに便利で、最後にlocalに戻しておくとよい
mean=.'(+/y)%#y'
3 : mean
3 : '(+/y)%#y'
13 : mean
+/ % #
他の品詞についても、それぞれに呼応して10~12にコロンを付して変換できる。
(ただし変換が可能な場合に限る。)
Jはリリ-ス2から制御構文を採用した。制御構文は、明示的定義で 利用できる。
制御構文は他の言語とあまり変わらない。
for_abc は for_ctr のようにして用いるとcounter文が省略できる。
Aが「0」でない(真の)ときB1を実行し、Aが「0」でC1が「0」でないときに B2を実行し、さらにC1が「0」でC2も「0」のときB3を実行する。
zero=: 3 : 0 if. 0=y do. 'zero' else. 'nonzero' end. )
zero 3 nonzero zero 0 zero
pzm=: 3 : 0
if. y=0 do.":0
elseif. y>0 do.":1
elseif. y<0 do.":_1 end.
)
pzm (L:0) 3 ; 0 ; _3 +-+-+--+ |1|0|_1| +-+-+--+
Aが「0」でない(真である)限りBを実行する。
まずBを実行し、Aが「0」でない(真である)限りBを実行する。
fact=:3 : 0
f=.n=.1+y
while. n>1 do. f=.f*n=.n-1 end.
)
fact ("0) i.5
1 2 6 24 120
!i.6
1 1 2 6 24 120
box=:3 : 0
b=.'' [ n=.>:y
whilst. n>1 do.
b=.b,
box 4
+-+---+-----+-------+
|0|0 1|0 1 2|0 1 2 3|
+-+---+-----+-------+
for
- try. B1 catch. B2 end.
B1を実行し、エラーがあればB2を実行する。
- for. B1 do.B2 end.
「B1」の回数だけ「B2」を実行する。
sum=:3 : 0
try. +/1+i.0>.y
catch.'miss!' end.
)
sum 10
55
sum 'a'
miss!
fact1=:3 : 0
f=.n=.((]>:0:)*1:>.|)y
for.i.<:n do. f=.f*n=.<:n end.
)
fact1 ("0) i.6
1 1 2 6 24 120
iota=:3 : 0
s=.0:`$@.(]=0:) y
for_j. i.|y do.
if.j=0 do. continue. end.
s=.s,j
end.
|.^:(_1=*y)s
)
iota 5
0 1 2 3 4
iota _5
4 3 2 1 0
iota 0
select.
select.Y
case. 0 do.D1
case. 1 do.D2
case. 2 do.D3
end.
「Y=1,2,3」に呼応して「D1,D2,D3」を実行する。
- 【さらに、次のような制御命令も用意されている】
- break.
while(whilst) 構文から抜け出す。
- continue.
while(whilst) 構文を続ける。
- goto_name. ラベル名
label_xyz(name) へジャンプする。
- label_name.
goto のジャンプ先
- return. 構文の流れから抜け出す。
case=:3 : 0
select. y
case. 0 do. i.1
case. 1 do.i.2
fcase.2 do.i.3
end.
)
case (L:0) {@> >:i.3
+-+---+-----+
|0|0 1|0 1 2|
+-+---+-----+
L:0による並列演算
csum=: 3 : 0
for_ctr. i. # y do.
1!:2&2 tmp=. ctr{y
end.
)
- for_xyz
xyzに任意の文字を入れてカウンターに用いる
(i,j)はJでは至る所に用いられているので注意
test_forabc=: 3 : 0
A=: 10+i.10
ANS=. 0
for_ctr. i. 10 do.
ANS=. ANS+tmp=. ctr{A
end.
ANS
)
test_forabc ''
145
再帰
再帰のprimitive($:) が復活したようだ。
その使用法と最近出来たM.(Memo) と合わせて効果を計測する。
\[ ! 3 \rightarrow 3 \times 2 \times 1 \rightarrow 6 \]
Jの階乗のprimitiveは(!)であり、良く錬成されていて早い。
! i.10
1 1 2 6 24 120 720 5040 40320 362880
ts '! i.10'
6.05313e_6 896
ここでは再帰の学習のため再帰を用いた3様の階乗を用いる。
ScriptはChris.Burk and Cliff Reiterによる
- 明示型で記述
fac1=: 3 : 0
if. y<:1 do. 1
else. y * fac1 y-1
end.
)
- 関数型の再帰。
fac2=: 1: `(*fac2@<:)@.*
- 再帰の\it{primitive}($:)を用いる。
fac3=: 1:`(*$:@<:)@.*
-
また実行速度と\it{Memo M.}の有効性も計測する
fac10=: fac1 M.
fac20=: fac2 M.
fac30=: fac3 M.
-
- [timer] 外部接続詞を用いて実行速度と使用spaceを計測する
ts=: (6!:2),7!:2
- [各scriptと計算結果]
fac1 "0 i.10
1 1 2 6 24 120 720 5040 40320 362880
fac2 "0] i.10
1 1 2 6 24 120 720 5040 40320 362880
fac3 "0] i.10
1 1 2 6 24 120 720 5040 40320 362880
- [計測結果]
- fac1 M.の方が幾分早い
ts 'fac1 "(0) i.100'
0.0394941 148288
ts 'fac10 "(0) i.100'
0.0352531 130944
- fac2。fac1より高速
ts 'fac2 "(0) i.100'
0.0139541 46464
ts 'fac20 "(0) i.100'
0.0137531 48320
- fac3はfac2より早い。M.の効果はない。Tuningが進むとM.の効果は
相殺されるようだ。
ts 'fac3 "(0) i.100'
0.00592404 46272
ts 'fac30 "(0) i.100'
0.00655782 48320
関数型の再帰スクリプトは難解であり、単独の科学技術計算やprogram
,logicの学習に限定した方が無難である。
Mapped file
Jには更に直接メモリ周りを扱うMapped fileの機能がある。
詳細はLABのtutorial参照