There’s none: only evaluation from right to left. Although adverbs and conjunctions are applied first.
gvar =. 23
fun1 =: 3 : 0
gvar + y
)
fun2 =: 3 : 0
gvar =: 7
gvar + y
)
fun1 3
fun2 3
fun1 3
gvar =. 23
fun1 =: 3 : 0
gvar + y
)
fun2 =: 3 : 0
gvar =. 7
gvar + y
)
fun1 3
fun2 3
fun1 3
23 = 34
23 = 23
Result is just a number:
10 + 3 = 3
There are 9 control structure patterns:
convert =: dyad : 0
if. x = 'c'
do. *: y
else. %: y
end.
)
'c' convert 4
'f' convert 4
x =: 3 : 0
if. y do. 2 else. 3 end.
)
x 0
x =: 3 : 0
if. y = 1 do. 2 elseif. y = 2 do. 3 elseif. 1 do. y end.
)
x 1
x 2
x _10
x =: 3 : 0
try. 1 catch. 2 end.
)
x 1
Locale is equivalent to a namespace:
abc_def_ =: 2
is like def::abc = 2;
in C++.
Locale defaults to base if elided:
abc_base_ =: 4
abc__
depending on argument
list nouns
a =. 23
b =. 24
a_q_ =. 25
w_q_ =. 26
names 0
names_q_ 0
list verbs
foo =: 3 : 0
y * y
)
foo 5
names 3
list locale names
names 6
'n' names_z_ 3
NB. defines arg y as "a" in global locale
f_q_ =. 3 : 'a =: y'
a =. 23 NB. define a in the base locale
a_q_ =. 24 NB. define a in locale q
f_q_ 100
a
a_q_
names_z_ 0
names_z_ 3
scripts ''
scripts 'v'
load 'convert'
toupper 'testing 1 2 3'
centigrade =. 3 : 0
t1 =. y - 32
t2 =. t1 * 5
t3 =. t2 % 9
)
load 'debug'
dbss 'centigrade *:*'
dbr 1
dbrun ''
a =. 12 24 47
b =. 12 34 45
a
b
a =. 12 24 47
0 { a
2 { a
a =. 1 2
b =. a , 3
b , 4
a =. 12 24 47
# a
|. 'abcdefg'
|. i.10
addlists =: dyad : 0
r =. ''
count =. #x
i =. 0
while. i < count do.
left =. i { x
right =. i { y
sum =. left + right
r =. r, sum
i =. i + 1
end.
r
)
2 3 4 addlists 4 5 6
adda =: dyad : 0
r =. ''
count =. #x
i =. 0
while. i < count do.
r =. r , (i{x) + (i{y)
i =. i + 1
end.
r
)
2 3 4 adda 4 5 6
addb =: 4 : 'x + y'
2 3 4 addb 4 5 6
2 3 4 + 4 5 6
1 + 2 3 4
2 3 4 + 1
this works for - * % = < <: as well:
2 4 6 * 7 8 9
2 * 2 3 4
2 3 4 * 2
5 6 7 % 2
2 3 4 - 3
2 3 4 = 7 3 8
2 < 0 1 2 3 4 5
2 <: 0 1 2 3 4 5
't' = 'testing'
approx range
i. 6
5 $ 7
Random number from 0 to arg.
? 10
? 10
? 10
? 10
? 0
combine $ ?
5 $ 100
? 5 $ 100 NB. ? 100 100 100 100
3 ^ 2
2 ^ 3
with 1 on left gives sin
i.7
1 o. i.7
load 'plot'
plot 5 10 23 45 8
load 'plot'
plot 2 ^ i.5
load 'plot'
plot ? 50 $ 100
load 'plot'
'TITLE myplot;TYPE bar' plot 2 ^ i.5
load 'plot'
plot 1 o. 0.1 * i.200
23 ‘a’
23 24 25 ‘this is a string’
Can’t be written to, only created with $.
2 3 $ 7
2 3 $ i.6
3 4 $ 'abcdefghijklmnopqrstuv'
2 3 $ 7 8
a =. 2 3 $ 7
$ a
i.2 3
2 3 4 $ i.24
i. 2 3 4
a =. 4 2 3 $ 'abcdef'
$ a
a =. 4 2 3 $ 'abcdef'
#$ a
#$ i. 2 3
#$ i.2
#$ 1
#$ ''
m =. i. 2 2
NB. add 2x2 matrices
m + 2 2 $ 10 11 12 13
NB. add numer to 2x2 matrix
10 + m
NB. add vector to each row
10 20 + m
NB. add vector to each col
10 20 + "1 m
approx reduce. +/ 1 2 3 is equivalent to 1 + 2 + 3.
+/ 1 2 3
a =. i. 3 4
a
+/ a
a =. i.5
a +/ a
a =. i.5
a */ a
0 1 +/ 0 1
0 1 */ 0 1
0 1 +./ 0 1
0 1 +:/ 0 1
0 1 *./ 0 1
0 1 *:/ 0 1
load 'plot'
plot 1 2 o. / 0.2 * i.60
b =. < 2 3 4
b
b =. < 2 3 4
c =. < 4 7 9
d =. b , c
d
2 3 4 ; 4 7 9
'abc' ; 4 7 9
(2 3 $ 'abcdef') ; (i. 3 4) ; 23
Boxes the left agument always, but right only if it’s not already boxed:
'abc' ; 'defg' ; 'hijl'
'abc' ; ('defg' ; 'hijl')
'abc' ; < 'defg' ; 'hijl'
Inverse of box. Applied to a noun that’s already open, has no effect.
a =. 1 2 3 ; 5 6 7
a
> a
Each atom is opened and the partial results are extended to fit into the result frame.
a =. 1 ; 2 3 ; 4 5 6
a
> a
Gets extended with spaces
> 'abc' ; 'defg' ; 'hijkl'
> 1 2 3 ; 'asdf'
a =. 5 7 9 4 8
3 { a
0 { a
2 4 { a
2 0 4 { a
m =. i. 3 4
m
0 { m
2 1 { m
1 { i. 2 3 4
If left argument of { is boxed, then it’s opened and each of its items gives the indexes along successive axes of the right argument.
m =. i. 3 4
m
(< 1 2) { m
m =. i. 3 4
(<1) { m
d =. i.2 3 4
d
(< 1 2 3) { d
(< 1 2) { d
m =. i. 3 4
m
(< 0 2 ; 0 2 3) { m
] d =. i.2 3 4
(< 0 1 ; 0 2 ; 2 3) { d
] m =. i. 3 4
(< 0 1 2 ; 2 3) { m
When left argument isn’t a box, standard rules apply for { (it has left rank 0):
] m =. i. 3 4
(0 2 ; 2 3) { m
(0 0 ; 1 1 ; 2 2) { m
change_index_two =. 2}
15 change_index_two 5 6 7 8
15 (2}) 5 6 7 8
23 (1 4}) 7 7 7 7 7
23 24 (1 4}) 7 7 7 7 7
'pd' 1 3} 'ooooo'
m =. i. 3 4
1 { m
23 23 23 23 (1}) m
m =. i. 3 4
(2 4 $ 23 23 23 23 24 24 24 24) (1 2}) m
m =. i. 3 4
12 ((< 1 2 ; 0 3)}) m
m =. i. 3 4
(2 2 $ 23 24 25 26) ((< 1 2 ; 0 3)}) m
{. 5 6 7
{: 5 6 7
}. 5 6 7
}: 5 6 7
3 {. i.8
2 3 {. i.3 4
2 3 {. i.3 4
5 {. 5 6 7
4 5 {. i. 2 3
1 }. 2 3 4
1 2 }. i. 3 4
3 2 1 2 3 # 'abcde'
It’s equivalent to:
0 0 0 1 1 2 3 3 4 4 4 { 'abcde'
means to use last element as splitter and include it
< ;. 2 'how now brown cow '
# ;. 2 'how now brown cow '
< ;. 2 (1 2 3 1 4 5 1)
# ;. 2 (1 2 3 1 4 5 1)
means to use last element as splitter and not include it
< ;. _2 'how now brown cow '
# ;. _2 'how now brown cow '
< ;. _2 (1 2 3 1 4 5 1)
# ;. _2 (1 2 3 1 4 5 1)
a =. 2 3 4 _1 5 3 2 _1 23 45 65 132 _1
< ;. _2 a
# ;. _2 a
+/ ;. _2 a
< ;. 1 'madam i''m adam'
< ;. _1 'madam i''m adam'
1 0 0 0 1 0 0 < ;. 1 'abcdefg'
d =. 'the test is the thing'
'the' E. d
Apply op to boxed items
a =. 10 12 13 ; 2 3 ; 4 5 6 8 3
a
+/ each a
,,*/ each a
|. each a NB. reverse each
>./ each a NB. max over each
a =. 10 12 13 ; 2 3 ; 4 5 6 8 3
23 , each a NB. append each
5 < each a NB. compare each to 5
1 |. each a
A train is a sequence of two or three words in a row that is given a special meaning. A train of two words is a hook and is evaluated as follows:
(f g) y | evaluates as | y f g y |
x (f g) y | evaluates as | x f g y |
Divide all list elements by its max.
a =. 3 5 8 2 7
>./ a NB.max
a % (>./ a) NB.divide by max
(% >./)a NB.simplify
A train of three verbs is a fork and is evaluated as follows:
(f g h) y | evaluates as | (f y) g (h y) |
x (f g h) y | evaluates as | (x f y) g (x h y) |
Average:
a =. 5 9 12
(+/ a) % (# a)
(+/ % #) a NB. same as above
mean =. +/ % #
mean i.999
With a constant left argument returns a derived monad that is the verb on the right with constant left arg
add3 =: 3 & +
add3 i.3
plus =. +
sumover =. +/
maxover =. >./
scale =. % >./
mean =. +/ % #
fahrenheit =: 3 : 0
t1 =. y * 9
t2 =. t1 % 5
t3 =. t2 + 32
)
fahrenheit 100
fahrenheit 200
fahrenheit in one line
fa =: 3 : '(y * 9 % 5) + 32'
fa 100
fa 200
rearrange the terms
fa =: 3 : '32 + ((9 % 5) * y)'
fa 100
fa 200
Create auxiliary verbs using bond &:
add32 =: 32 & +
ninefifthtimes =: (9 % 5) & *
add32 ninefifthtimes 100
add32 ninefifthtimes 200
Use atop conjunction @ to compose add32 and ninefifthtimes:
add32 =: 32 & +
ninefifthtimes =: (9 % 5) & *
fc =: add32 @ ninefifthtimes
fc 100
fc 200
add32 =: 32 & +
ninefifthtimes =: (9 % 5) & *
fc =: add32 @ ninefifthtimes
fc
fz =. fc f.
fz
(u @ v) y evaluates as u v y
Like all adverbs, takes argument on the left. Takes a tacit definition and replaces names with their definitions.
fz =: 32&+@(1.8&*)
cz =: fz inverse
fz 100
cz 212
fz 0
cz 32
fx =: 3 : '32 + y * 9 % 5' NB. 3 explicit
ft =: 13 : '32 + y * 9 % 5' NB. 13 tacit
ft
writefile =: 1!:2
fn =. < '/tmp/test.txt'
'testing 1 2 3' writefile fn
readfile =: 1!:1
fn =. < '/tmp/test.txt'
data =: readfile fn
data
writefile =: 1!:2
numtab =. i.4 5
cdata =. ": numtab
ddata =. cdata ,"1 LF
ddata
$ ddata
ldata =. , ddata
ldata
$ ldata
ldata writefile < '/tmp/test.txt'
'abc' , LF , 'def'
rdata =. 1!:1 <'/tmp/test.txt'
dlf =. toJ rdata NB.convert line breaks
bdata =. cutopen dlf
bdata
ndata =. 0 ". each bdata
ndata
> ndata
0 ". '5 2 7'
1 + 0 ". '5 2 7'
left arg is value to use if conversion fails
0 ". '5 7.5 23.b 8'
writetable =: dyad : 0
d =. ": x
d =. d , "1 LF
d =. toHOST , d
d 1!:2 y
)
readtable =: 3 : 0
d =. 1!:1 y
d =. toJ d
d =. cutopen d
d =. 0 ". each d
d =. > d
)
writetable =: 4 : '(toHOST,(": x),"1 LF) 1!:2 y'
(i.4 4) writetable < '/tmp/test.txt'
A boxed list stored in a file
load 'jfiles'
f =. '/home/oleh/data.jf'
jcreate f
'first component' jappend f
(1.5 + i.2 3) jappend f
('asdf' ; 23) jappend f
(< 'mum' ; 'dad') jappend f
jsize f
jread f ; 0
jread f ; 1
jread f ; 2
jread f ; 3
jread f ; 4
load 'files'
fn =. '/tmp/text.txt'
data =. 'abc' , LF , 'bc' , LF , 'b' , LF
data fwrite fn
fread fn
c | conjunction |
n | noun |
d | dyad |
v | ambivalent verb |
9!:3 (5)
+/ % #
9!:3 (2 4 5)
+/ % #
pss =: +/\
x =: }. i.7
x
pss x NB. partial sums
sss =: +/ \.
sss |. x
|. sss |. x
sss &. |. x
<\ x NB. Box prefix scan
<\. x NB. Box suffix scan
s =: sort =: /:~
numb =: 3 1 4 1 [ char =: 'cage'
poem =: 'i sing' , 'of olaf' ,: 'glad and big'
(,.s numb) ; (,.s char) ; poem ; (s poem) ; s"1 poem
n16 =: m =: 3 1 4 , 2 0 5 ,: 1 4 1
d17 =: ip =: +/ . * NB. inner (matrix) product
m18 =: L =: m & ip
L
L x =: 1 2 5
h =: 'L' f.
h x
ip =: -/ . *
L x
h x
d0 =: +/ NB. Addition table
d1 =: */ NB. Multiplication table
d2 =: >./ NB. Maximum table
d3 =: [ by ] over +/ NB. Bordered addition table
d4 =: by =: ' ' & ; @ ,. @ [ ,. ] NB. Format function
d5 =: over =: ({. ; }.) @ ": @ , NB. Format function
m6 =: +/ ~ @ i. NB. Addition table on first y integers
m7 =: bc =: !/~ @ i. NB. Binomial coefficients of order y
a8 =: ft =: 1 : 'x/~ @ i.' NB. Function table
a9 =: bft =: 1 : 'i. by i. over x/ ~ @ i.' NB. Bordered function table (explicity definition)
2 3 5 (d0 ; d1 ; d2) 0 1 2 3 4 5
m0 =: 1 & + NB. increment >:
m1 =: + & 1 NB. "
m2 =: _1 & + NB. decrement <:
m3 =: - & 1 NB. "
m4 =: 1 & - NB. Not -. (logical and probability complement)
m5 =: 1 & ~: NB. "
m6 =: 0 & = NB. "
m7 =: 0 & - NB. Negate - (arithmetic)
m8 =: _1 & * NB. "
m9 =: * & _1 NB. "
m10 =: 2 & * NB. Double +:
m11 =: * & 2 NB. "
m12 =: 3 & * NB. Triple
m13 =: * & 3 NB. "
m14 =: 0j1 & * NB. j. (Multiply by sqrt(-1))
m15 =: ^ @ j. NB. r. (Complex # on unit circle at y radians)
m16 =: 1p1 & * NB. pi times
m17 =: 0.5 & * NB. Halve -:
m18 =: * & 0.5 NB. "
m19 =: % & 2 NB. "
m20 =: 1 & % NB. Reciprocal %
m21 =: ^& _1 NB. "
m22 =: ^& 2 NB. Square *:
m23 =: ^& 3 NB. Cube
m24 =: ^& 0.5 NB. Square root %:
m25 =: ^& 1r2 NB. "
m26 =: 2 & %: NB. "
m27 =: ^& (% 3) NB. Cube root
m28 =: ^& 1r3 NB. "
m29 =: 3 & %: NB. "
m30 =: (^1) & ^ NB. Exponential ^
m31 =: 1x1 & ^ NB. "
m32 =: 1x1 & ^. NB. Natural log ^.
m33 =: 10 & ^ NB. power 10
m34 =: 10 & ^. NB. Base-10 log
NB. (1+ (floor (log10 (max 1 (ceil x)))))
m35 =: >: @ <. @ (10 & ^.)@(1 & >.) NB. # of digits needed to represent integer y
m36 =: # @ (10 & #. ^: _1)"0 NB. "
| 6 _6 3j4
3 | 0 1 2 3 4 5 6 7
# 3 4 5
y =: 6 7 8 9 10
1 1 0 1 0 # y
(y > 7) # y
>. _1.7 1 1.7
3 >. 1 3 5
>./ 1 6 5
>: _2 3 5 6.3
3 >: 1 3 5
i.5
'abra' i. 'r'
halve =: -:
mult =: 1: + (* 3:)
odd =: 2 & |
halve 6
mult 6
odd 6
collatz =: halve ` mult @. odd
collatz 17
- If the balance is $100 or more, the bank pays interest of 0.5%
- If the balance is negative, the bank charges interest at 2%.
- Otherwise the balance is unchanged.
pi =: * & 1.005 NB. pay interest
ci =: * & 1.02 NB. charge interest
uc =: * & 1 NB. unchanged
case =: (>: & 0) + (>: & 100)
case _50 0 1 100 200
PB =: ci ` uc ` pi @. case
PB _50
PB 0
PB 1
PB 100
PB 200
PB _50 0 1 100 200
(PB"0) _50 0 1 100 200
empty =: # = 0:
first =: {.
rest =: }.
Sum =: (first + Sum @ rest) ` 0: @. empty
Sum 1 1 2
Ack =: 4 : 0
if. x = 0 do. y + 1
elseif. y = 0 do. (x - 1) Ack 1
elseif. 1 do. (x - 1) Ack (x Ack y - 1)
end.
)
2 Ack 3
3 Ack 3
ack =: c1 ` c1 ` c2 ` c3 @. (#. @ (,&*))
c1 =: >: @ ] NB. 1+y
c2 =: <: @ [ ack 1: NB. (x-1) ack 1
c3 =: <: @ [ ack [ ack <: @ ] NB. (x-1) ack x ack y
2 ack 3
3 ack 3
Verb applied multiple times over.
(+: ^: 3) 1
With arg _ find the fixed point
p =: 3 : '2.8 * y * (1 - y)'
(p ^: 0 1 2 3 19 20 _) 0.5
(f ^: g) y means f ^: (g y) y
(+: ^: %:) 16
halve =: -:
even =: 0: = 2 & | NB. returns 0 or 1
foo =: halve ^: even NB. halve 0 or 1 times
(foo"0) i.10
w =: (halve ^: even) ^: _ NB. keep halving while even
w 48
The following are equivalent:
f =: -:
g =: 0: = 2 & |
w1 =: f ^: g ^: _
w2 =: 3 : 0
while. (g y)
do. y =. f y
end.
y
)
w1 48
w2 48
x (u ^: w) y means ((x & u) ^: w) y
((3 & +) ^: 2) 0
3 (+ ^: 2) 0
e =: 3 : '(+/ y) % #y'
t =: 13 : '(+/ y) % #y'
e
t
e 1 2 3
t 1 2 3
ed =: 4 : 'y % x'
td =: 13 : 'y % x'
ed
td
(2 ed 6),(2 td 6)
k =: 99
p =: 3 : 'y + k'
q =: 13 : 'y + k'
p
q
(p 6) ; q 6
k =: 0
(p 6) ; q 6
C =: @:
g =: %:
foo =: 13 : '(f C f y) , g y'
foo
f =: *:
foo 4
scale =: * & (5 % 4)
scale
scale 8
SCALE =: * & 5 % 4
SCALE
Second one is (* & 5) applied to (% 4). It’s explained by conjunctions having short right scope.
z =: 3 & + @: *:
z 2
Adverbs and conjunctions have long left scope. That means that the left argument of @: is the entire 3 & +
a =: 5
b =: 4
f =: * & (a % b)
f
a =: 5
b =: 4
w =: *
g =: w & (a % b)
g
When a new name is encountered, it is assumed to be a yet-to-be-defined verb.
h =: ytbd & (5 % 4)
ytbd =: *
h 8
A sequence of hitherto-unknown names is assumed to be a train of verbs:
ctof =: shift @ scale
shift =: + & 32
scale =: * & (9 % 5)
ctof
ctof 0 100
scale =: * & 2
ctof 0 100
CTOF =: 3 : 0
shift =. + & 32
scale =. * & (9 % 5)
shift @ scale y
)
CTOF 100
ctof =: shift @ scale
shift =: + & 32
scale =: * & (9 % 5)
ctof
ctof f.
y =: lambda * x * (1 - x)
P =: 3 : 'lambda * y * (1 - y)'
x =: 0.6
lambda =: 3.0
P x
lambda =: 3.5
P x
tP =: 13 : 'lambda * y * (1 - y)'
tP
erase <'lambda'
tP =: 13 : 'lambda * y * (1 - y)'
tP
lambda =: 3.5
tP x
Compromise “fully tacit”
tP =: (3 : 'lambda') * ] * (1: - ])
lambda =: 3.5
tP 0.6
Compromise “exact equivalent”
lambda =: 3.5 " 0
tP =: lambda * ] * (1: - ])
tP 0.6
lambda =: 3.75 " 0
tP 0.6
type : body
monadic or ambivalent verbs
strictly dyads
with expansion/freeze
noun | 0 |
adverb | 1 |
conjunction | 2 |
verb | 3 |
monad | 3 |
dyad | 4 |
def | : |
define | : 0 |
multiline definition, finish with )
PosDiff =: 4 : 0
larger =. x >. y
smaller =: x <. y
larger - smaller
)
3 PosDiff 4
PosDiff =: 4 : ('la =. x >. y' , LF , 'sm =. x <. y' , LF , 'la - sm')
PosDiff
3 PosDiff 4
PosDiff =: 4 : ('la =. x >. y' ; 'sm =. x <. y' ; 'la - sm')
PosDiff
3 PosDiff 4
Has both monadic and dyadic case. Monadic case is written first, then a line of a solo colon, then dyadic case.
log =: 3 : 0
^. y
:
x ^. y
)
log 2.71
10 log 100
PosDiff =: 4 : '(x >. y) - (x <. y)'
3 PosDiff 4
4 PosDiff 3
PosDiff =: dyad def '(x >. y) - (x <. y)'
3 PosDiff 4
'day mo yr' =: 16 10 95
day , mo , yr
('day' ; 'mo' ; 'yr') =: 17 11 96
day , mo , yr
N =: 'day' ; 'mo' ; 'yr'
(N) =: 18 12 97
day , mo , yr
rq =: 3 : 0
'a b c' =. y
((- b) (+ , -) %: (b ^ 2) - 4 * a * c) % (2 * a)
)
rq 1 1 _6
rq 1 ; 1 ; _6
sum =: 3 : 0
if.
length =. # y NB. T block
length = 0 NB. T block
do.
0 NB. B1 block
else.
first =. {. y NB. B2 block
rest =. }. y NB. B2 block
first + sum rest NB. B2 block
end.
)
ClaTePo =: 3 : 0
if. y > 80 do. 'too hot'
else.
if. y < 60 do. 'too cold'
else. 'just right'
end.
end.
)
ClaTePo 70
class =: 3 : 0
t =. 4 !: 0 < y
if. t = 0 do. 'noun'
elseif. t = 1 do. 'adverb'
elseif. t = 2 do. 'conjunction'
elseif. t = 3 do. 'verb'
elseif. 1 do. 'bad name'
end.
)
class 'class'
class 'oops'
class =: 3 : 0
select. 4 !: 0 < y
case. 0 do. 'noun'
case. 1 do. 'adverb'
case. 2 do. 'conjunction'
case. 3 do. 'verb'
case. do. 'bad name'
end.
)
class 'class'
class 'oops'
class =: 3 : 0
select. 4 !: 0 < y
case. 0 do. 'noun'
case. 1 ; 2 do. 'operator'
case. 3 do. 'verb'
case. do. 'bad name'
end.
)
o =: @:
class 'o'
class 'oops'
fact =: 3 : 0
r =. 1
while. y > 1
do. r =. r * y
y =. y - 1
end.
r
)
fact 5
whilst. T do. B end.
means
B while. T do. B end.
for_a. A do. B end.
means
for each item a in array A, execute block B.
Sum =: 3 : 0
r =. 0
for_term. y do. r =. r + term end.
r
)
Sum 1 2 3
a_index is also available similar to Python’s enumerate
f3 =. 3 : 0
r =. 0 2 $ 0
for_item. y do. r =. r , (item_index ; item) end.
r
)
f3 'ab' ; 'cdef' ; 'gh'
Suppose we want an adverb A s.t. u A means u ” 0
A =: 1 : 'u"0'
f =: < A
f 1 2
W =: 1 : '<"u'
0 W
z =: 'abc'
0 W z
1 W z
y =: 1 0 2 3
1 0 1 1 # y NB. dyad Copy
> & 0 y NB. select items greater than 0
(> & 0 y) # y
f =: > & 0 # ] NB. fork to select items >0
f y
B =: 1 : 'u # ]'
g =: >&0 B
g 1 0 _2 3
u THEN v
is to be v @: u
THEN =: 2 : 'v @: u'
h =: *: THEN <
h
h 1 2 3
Count items greater than 0
foo =: # @: (> & 0 # ])
foo 5 0 _7 3
Generalize to a conjunction
u C v
is to be u @: (v # ])
C =: 2 : 'u @: (v # ])'
f =: # C (> & 0)
f 5 0 _7 3
Previous conjunction as multiline
D =: 2 : 0
select =: v # ]
u @: select
)
f =: # D (> & 0)
f
f 5 0 _7 3
E =: 2 : 0
select =. v # ]
(u @: select)f.
)
E
g =: # E (> & 0)
g
y =: 1 0 2 3
g y
Note that g unlike doesn’t have local names.
Write a function that replaces each number on the list by the mean of its two neighbors, assuming 0 neighbor for first and last.
sh =: |. !. 0 NB. shift, entering zero
prev =: _1 & sh NB. right shift
next =: 1 & sh NB. left shift
halve =: -:
smoo =: halve @: (prev + next)
N =: 6 2 8 2 4
N
prev N
next N
smoo N
To have circular smoothing, we need sh
to become |.
(rotate).
SMOO =: 1 : ('sh =. u' ; 'smoo f.')
rv =: |. SMOO
rv
smoo N
rv N
Suppose we want a conjunction u H v
equivalent to
3 : 0
z =. v y
y u z
)
H =: 2 : 0
U =. 5!:5 < 'u'
V =. 5!:5 < 'v'
string =. 'z =. ', V , 'y', LF
string =. string , 'y ', U , ' z', LF
3 : string
)
foo =: + H *:
foo
foo 5
This is similar to
(defun H (u v)
(read (format "(lambda(x) (%s x (%s x)))"
u v)))
(setq foo (H "(lambda(x y)(+ x y))"
"(lambda(x)(* x x))"))
(funcall foo 5)
K =: 2 : 0
z =. v y
y u z
)
bar =: + K *:
bar
bar 5
This is similar to
(defun H (u v)
`(lambda(x)
(funcall ,u x (funcall ,v x))))
(setq foo (H (lambda(x y)(+ x y))
(lambda(x)(* x x))))
(funcall foo 5)
Consider a monadic verb selecting items greater than 0:
e =: 3 : '(> & 0 y) # y'
y =: 1 0 2 3
e y
Generalize to form an adverb which selects items according to a supplied test-verb, i.e. a filter:
F =: 1 : '(u y) # y'
>&1 F y
<&2 F y
Suppose u W
is to be 4 : '(u x) + (u y)'
W =: 1 : 0
:
(u x) + (u y)
)
(*: 2) + (*: 16)
2 (*: W) 16
Suppose u T
is to be =4 : ‘x (u”0 0) ” 0 1 y’,
i.e. a self-made / (table).
T =: 1 : 0
:
x ((u"0 0)"0 1) y
)
1 2 3 + T 4 5 6 7
G =: 2 : 0
selected =. (v y) # y
u selected
)
y
# G (> & 0) y
H =: 2 : 0
:
(u x) + (v y)
)
(*: 2) + (%: 16)
2 (*: H %:) 16
Arguments to operators can be named m
and n
instead of u
and v
to constrain arguments to be nouns.
display =: (1 !: 2) & 2
R =: 2 : 0
display 'hello'
select =. v # ]
(u @: select) f.
)
f =: # R (> & 0)
f 1 0 2 0 3
S =: 2 : 0
display 'hello'
selected =. (v y) # y
u selected
)
g =: # S (> & 0)
g 1 0 2 0 3
f =: 3 : '2.8 * y * (1 - y)'
FFF =: 1 : '(u ^: _) 0.5'
p =: f FFF
p
where =: 2 : 'u'
mean =: sum % # where sum =: +/
mean 1 2 3 4
(z + 1) * (z - 1) where z =: 7
CS =: @: *:
- CS
- CS 2 3
- *: 2 3
Suppose we need u K
is to be @: u
K =: 1 : '@: u'
L =: *: K
- L
- L 2 3
Gerund represents a list of verbs. It’s useful mainly for supplying a list of verbs as a single argument to an operator.
abs =: + ` - @. (< & 0)
abs
abs _3
G =: + ` - ` abs
G
Verbs packed into a gerund can be unpacked again with the built-in adverb “Evoke Gerund” denoted by (`: 6).
EV =: `: 6
f =: 'f' & ,
g =: 'g' & ,
H =: f ` , ` g
foo =: H EV
foo
foo 'o'
Individual verbs can be unpacked by indexing the boxed list H
and
the applying EV
.
H
2 { H
vb =: (2 { H) EV
vb
vb 'o'
H
1 2 { H
tr =: (1 2 { H) EV
tr 'a'
APPEND =: `: 0
sum =: +/
count =: #
mean =: sum % count
G1 =: count ` sum ` mean
G1
foo =: G1 APPEND
foo
foo 1 2 3
(u`v`w...) APPEND y
means (u y),(v y),(w y),...
G2 =: 2 2 $ G1
G2
G2 APPEND 4 5
abs =: + ` - @. (< & 0)
abs 6
abs _6
Here, @. takes a verb on the right. It can also take a noun on the right.
G =: + ` - ` %
f =: G @. 0
f
1 f 1
G
h =: G @. 0 2
h
h 4
G
EV =: `: 6
(G @. 0 2) 4
((0 2 { G)) EV 4
T =: * (- 1:)
T 3
T 4
foo =: (* ` - ` 1:) @. (0 ; 1 2)
T
foo
foo 3
If G
is f`g`h
and X
is x0,1,x2,x3
then G/X
is x0 f x1 g x2 h x3
ger =: + ` %
ger/ 1 2 3
1 + 2 % 3
If the gerund is too short, it’s re-used cyclically. This means that a one-verb gerund is equivalent to a single inserted verb.
Recall power conjunction:
double =: +:
(double ^: 3) 1
As a variation, the number of iterations ca be computed by a verb
right-argument. The scheme is, for verbs u
and v
:
(u ^: v) y
means u ^: (v y) y
decr =: <:
double ^: (decr 3) 3
(double ^: decr) 3
More generally, the right argument can be given as a gerund, and the
verbs in it do some computations at the outset of the iteration
process.
u ^: (v1 ` v2) y
means u ^: (v1 y) (v2 y)
Verb to compute a Fibonacci sequence:
u =: , sumlast2
sumlast2 =: +/ @ last2
last2 =: _2 & {.
'o' 1 } 'baron'
Takes a gerund of three verbs:
x (U`V`W) } y
means (x U y) (x V y) } (x W y)
That is the new items, the indexes and the “old” array are all to be
computed from given x
and y
.
Define a verb R
to amend a matrix by multiplying its i
‘th row by
a constant k
. The left argument of R
is to be the list i k
and
the right argument is to be the original matrix.
R
is defined as the amend adverb applied to a gerund of 3 verbs.
i =: {. @ [ NB. x i y is first of x
k =: {: @ [ NB. x k y is last of x
r =: i { ] NB. x r y is (x i y)'th row of y
R =: ((k * r) ` i ` ]) }
For example:
M =: 3 2 $ 2 3 4 5 6 7
z =: 1 10 NB. row 1 times 10
M
(z i M) ; (z k M) ; (z r M)
z R M
(40 50) 1 } M
Define adverb A
to produce a fork-like verb:
x (f ` g ` h A) y
is to be (f x) g (h y)
A =: 1 : 0
f =. u @. 0
g =. u @. 1
h =. u @. 2
((f @ [) g (h @ ])) f.
)
To demonstrate A
, here is a verb to join the first item of x
to
the last of y
.
H =: {. ` , ` {:
zip =: H A
zip
'abc' zip 'xyz'
'abc' ({. @ [ , {: @ ]) 'xyz'
A combination of filter
, map
and reduce
.
ACC =: 1 : 0
com =. u @. 0
map =. u @. 1
fil =. u @. 2
((com/) @: map @: (#~ fil)) f.
)
For example, to compute the sum of squares of odd numbers in a given list:
+/ *: ((2 & |) # ]) 1 2 3 4
(+ ` *: ` (2 & |)) ACC 1 2 3 4
<"0 'abc'
A conjunction takes two arguments. If we supply only one, the result
is an adverb.
For example, an adverb to apply a given verb to each scalar
is ("0)
.
each =: " 0
< each
z =: < each 'abc'
z
The scheme is that for conjunction C
and noun N
,
(C N)
denotes an adverb such that
x (C N)
means x C N.
Argument to be supplied the the conjunction can be a noun or a verb,
on the left or on the right.
Note that this is similar to the bond &, except & isn’t necessary
because conjunctions don’t have a monadic case.
f =: 'f' & ,
g =: >
z =: 'a' ; 'b' ; 'c'
z
(f &. g) z
Define EACH
adverb to mean “inside each box”:
EACH =: &. >
f EACH
z
f EACH z
For adverbs A
and B
, the bident (A B)
denotes an adverb:
x (A B)
means (x A) B
cum =: /\
z =: 2 3 4
+ cum z
* cum z
A =: * ` NB. verb conjunction
B =: `: 6 NB. conjunction noun
H =: A B NB. compound adverb - a hook maker
<: A
<: A B
h =: <: H
h
h 5
It’s possible to rewrite the definition of a verb to an equivalent form by rearraning its terms. Suppose we start with a definition of the factorial function
f =: (* ($: @: <:)) ` 1: @. (= 0:)
f 5
The idea now is to rewrite f
to the form $: adverb
by a sequence
of steps.
A1 =: @. (= 0:)
g =: (* ($: @: <:)) ` 1: A1
f =: (* ($: @: <:)) ` 1: @. (= 0:)
g 5
f 5
A2 =: ` 1:
h =: (* ($: @: <:)) A2 A1
h 5
A3 =: (* `) (`: 6)
h =: (* ($: @: <:)) A2 A1
i =: ($: @: <:) A3 A2 A1
i 5
A4 =: @: <:
j =: $: A4 A3 A2 A1
j 5
A =: A4 A3 A2 A1
k =: $: A
k 5
m =: $: (@: <:) (* `) (`: 6) (` 1:) (@. (= 0:))
m 5
f
m
y =: 'abcde'
4 2 3 1 0 { y
p =: 4 2 3 1 0 & {
y
p y
p p y
p p p p p p y
p ^: 6 y
The permutation (4 2 3 1 0) can be represented as a cyle of 2 and a cycle of 3
C. 4 2 3 1 0
C. 3 1 2 ; 4 0
First representation is called direct, second is called cyclic.
Upper-case letters come before lower-case letters.
65 66 67 97 98 99 { a.
Complex numbers are ordered by the real part then the imaginary part.
n =: 0 1 _1 2j1 1j2 1j1
n /: n
With boxed arrays, the ordering is by the contents of each box.
The precedence is
numerical < empty < chars < boxed
[k =: (< 'abc') ; 'pqr' ; 4 ; '' ; 3
k /: k
low rank < high rank
[m =: 2 4 ; 3 ; (1 1 $ 1)
(# @ $ @ >) m
m /: m
If they have the same rank, compare elementwise:
1 2
< 1 3
,
3 3
< 3 3 3
a =: 2 3 $ 1 2 3 4 5 6
b =: 3 2 $ 1 2 5 6 3 4
c =: 1 3 $ 1 2 3
[u =: a ; b ; c
u /: u
Suppose we want to sort by abs.
x =: 2 1 _3
keys =: | x
x /: keys
The monadic verb |: will transpose a matrix, that is interchange the first and second axes.
The items which would be brought around by cyclic rotation can instead be replaced with a fill-term.
A shifting verb is written (|. !. f)
where f
is the fill-item.
ash =: |. !. '*' NB. alphabetic shift
nsh =: |. !. 0 NB. numeric shift
y =: 'abcde'
y ; (_2 ash y) ; (1 ash y)
z =: 2 3 4
z ; (_1 nsh z) ; (2 nsh z)
<\ 'abcde'
+/\ 0 1 2 3
+./\ 0 1 0 1 0
In the expression x f \ y
the verb f
is applied to successive
sections (“infixes”) of y
, each of length x
.
z =: 1 4 9 16
2 <\ z
3 <\ z
If x
is negative, then the sections are non-overlapping, in which
case the last section may not be full-length.
z =: 1 4 9 16
_3 <\ z
_2 <\ i.10
We can compute the differences between successive items, by choosing 2
for the section-length, and applying to each section a verb
“second-minus-first”, that is, ({: - {.)
smf =: {: - {.
smf 1 4
diff =: 2 & (smf\)
z =: 1 4 9 16
,. diff z
(f \. y)
applies f
to successively shorter suffixes of y
:
<\. 'abcde'
(x f \. y)
applies f
to the whole of y
with
successive sections removed, each being of length x
.
If x
is negative, then the removed sections are non-overlapping.
y =: 'abcde'
2 <\. y
_2 <\. y
Start with
T =: 0 : 0
1 2 3
4 5 6
19 20 21
)
$ T
+/ T = LF
T
is a character-string with 3 embedded line-feed chars.
Now cut T
into lines. Then eval them with “.
[ TBL =: (". ;. _2) T
*: TBL
frets =: ' ? !.'
t =: 'How are you?'
[ b =: t e. frets
Now the bitvector b
can be used to specify the frets for cutting
text t
into words:
b < ;. _2 t
Consider cutting a numeric vector into intervals such that each is in ascending sequence.
Compute a bitvector by scanning infixes of length 2, applying >/ to each pair of items. Where we get 1, the second item of the pair is the beginning of a new interval. We make sure the first item of all is 1.
data =: 3 1 4 1 5 9
2 ]\ data
2 >/\ data
] bv =: 1 , 2 >/\ data
data ,: bv
bv < ;. 1 data
First, create an example file.
text =: 0 : 0
What can be said
at all
can be said
clearly.
)
text (1 !: 2) < 'foo.txt'
Now read into a string and cut it:
string =: (1 !: 1) < 'foo.txt'
] lines =: (< ;. _2) string
Note that we rely here on LF for cutting. Windows has CRLF instead of LF. J follows the convention of the single LF regardless of the system. However CR have to be taken care of. Here’s how to strip it:
string =: (string ~: CR) # string
Secondly, depending on how the file of text was produced, we may not be able to guarantee that the last line is actually terminated.
tidy =: 3 : 0
y =. y , (LF ~: {: y) # LF NB. append LF if not already there
(y ~: CR) # y NB. remove CR
)
(< ;. _2) tidy (1 !: 1) < 'foo.txt'
x u ;. 3 y
applies u
separately to each of a collection
of subarrays extracted from y
.
These subarrays may be called tiles.
The size and arrangement of the tiles are defined by x
.
y =: 4 4 $ 'abcdefghijklmnop'
spec =: > 2 2 ; 2 2 NB. offset, shape
spec < ;. 3 y
Tiling may leave incomplete pieces(“shards”) at the edges. They’re included or excluded with 3 or _3.
sp =: > 3 3 ; 3 3
sp < ;. 3 y
sp < ;. _3 y
seteq =: *./ @: (e. , e.~)
1 2 3 seteq 3 1 2 1
1 2 3 seteq 1 2
Consider finding frequency-distribution of letters.
y =: 'hook'
~. y
(~. y) =/ y
= y
If we sum each row we obtain the counts, in the order of the letters in the nub.
y =: 'hook'
= y
+/"1 = y
The counts can be paired with the letters of the nub:
y =: 'hook'
~. y
(~. y) ;"0 (+/"1 = y)
Classify soil-type as acid, neutral or alkaline depending on pH.
classify =: ({ & 'ANL') @: ((>: & 6) + (> & 7))
classify 6
classify 4.8 5.1 6 7 7.1 8
data =: 7 5 6 4 8
] k =: classify data
k = 'A'
(k = 'A') # data
Now suppose we wish to count the items in each class.
data
[ k =: classify data
k #/. data
k </. data
The verb we apply can discover for itself the class of each separate argument, by classifying the first member:
u =: (classify @: {.) ; #
data
] k =: classify data
k u/. data
The general scheme for the “Key” is:
in x u/. y
take y
to be a list, and x
a list of keys,
and u
a verb to be applied separately to each class.
] y =: 4 5 6 7 8
] x =: classify y
u =: <
= x
(= x) (u @ #) y
x u/. y
y =: 'LETTUCE'
= y
(~. y) ;"0 +/"1 (= y)
u =: {. ; #
y u/. y
Suppose there are a number of publications, such as:
- “Pigs” by Smith, on the subject of pigs
- “Pets” by Brown, on cats and dogs
- “Dogs” by Smith and James, on dogs
and we aim to catalog such publications. We can use two tables called relations.
The authors-titles relation is:
] AT =: (". ;. _2) 0 : 0
'Smith' ; 'Pigs'
'Brown' ; 'Pets'
'Smith' ; 'Dogs'
'James' ; 'Dogs'
)
And the titles-subjects relation is:
] TS =: (". ;. _2) 0 : 0
'Pigs' ; 'pigs'
'Pets' ; 'cats'
'Pets' ; 'dogs'
'Dogs' ; 'dogs'
)
A method is as follows. Consider all possible pairs consisting of a
row at
from table AT
and a row ts
from table TS
.
Each pair at,ts
is of the form:
author ; title ; title ; subject
If title matches, i.e. item 1 matches item 2, then we extract author
and subject, i.e. items 0 and 3.
test =: 1 & { = 2 & {
extr =: 0 3 & {
These verbs can be plugged into a suitable conjunction to do the pairing. It writing this conjunction, we aim to avoid requiring the whole set of possible pairs to be present at the same time, since this set may be large. We also aim to avoid any duplicates in the result. Here is a first attempt.
PAIR =: 2 : 0
:
z =. 0 0 $ ''
for_at. x do.
for_ts. y do.
if. u at , ts do. z =. z , v at , ts end.
end.
end.
~. z
)
join =: test PAIR extr
AT join TS
The join
verb as defined above is slow, because the test
and
extr
verbs are applied to a single x,y
pair at a time - they are
scalar computations. Performance will be better if we can give these
verbs as much data as possible to work on at one time.
Here is a revised vector-oriented version of PAIR
and join
,
which still avoids building the entire set of pairs.
VPAIR =: 2 : 0
:
z =. 0 0 $ ''
for_at. x do.
z =. z , |: v (#~"1 u) |: at ,"1 y
end.
~. z
)
vjoin =: test VPAIR extr
AT vjoin TS
Symbols are for efficient computation with string data.
They’re a distinct data-type, in the same way as characters,
boxes and numbers.
A symbol is a scalar which refers to a string.
A symbol can be created by applying s:
to a boxed string.
] a =: s: < 'hello'
Although it looks like the original string with ` prepended, it’s a scalar:
# $ a
The original string is stored in a data-structure, maintained automatically by the J system, called the symbol-table. Strings aren’t duplicated so if there’s two references to the same string, they’re equal.
b =: s: < 'hello'
b = a
Note that this is a scalar comparison and not a string comparison.
sAT =: s: AT
sTS =: s: TS
sAT vjoin sTS
Symbols are lexicographically ordered to reflect the ordering of the original strings. Hence tables of symbols can be sorted:
sAT
/:~ sAT
A utility verb giving time in seconds to evaluate an expression, averaged over 4 executions:
time =: (8j5 & ":) @: (4 & (6 !: 2))
AT =: 100 $ AT
TS =: 100 $ TS
sAT =: 100 $ sAT
sTS =: 100 $ sTS
t1 =: time 'AT join TS' NB. scalar method, boxed strings
t2 =: time 'sAT join sTS' NB. scalar method, symbols
t3 =: time 'AT vjoin TS' NB. vector method, boxed strings
t4 =: time 'sAT vjoin sTS' NB. vector method, symbols
3 3 $ ' ' ; 'strings' ; 'symbols' ; 'scalar' ; t1 ; t2 ; 'vector' ; t3 ; t4
Suppose that data
is an array of symbols.
] data =: s: 2 2 $ 'hello' ; 'blah' ; 'blah' ; 'goodbye'
i.2 3 4
s: 2 2 $ 'fooommmmm' ; 'blurg' ; 'blah' ; 'bar'
s: 2 2 $ 'blah' ; 'bar' ; 'fooommmmm' ; 'blurg'
i =: ,((,|:)i.9 9),,./,./i.4$3
c =: (#=[:#~.)@-.&0
t =: [:(([:*/_9:c\])"1#])i&{+"1 1(>:i.9)*/[:i&=i.&0
r =: [:,`$:@.(0:e.,)[:;(<@t)"1
s =: 9 9&$@r@,
]m =: 9 9 $"."0'200370009009200007001004002050000800008000900006000040900100500800007600400089001'
s m
2 0 0 3 7 0 0 0 9 0 0 9 2 0 0 0 0 7 0 0 1 0 0 4 0 0 2 0 5 0 0 0 0 8 0 0 0 0 8 0 0 0 9 0 0 0 0 6 0 0 0 0 4 0 9 0 0 1 0 0 5 0 0 8 0 0 0 0 7 6 0 0 4 0 0 0 8 9 0 0 1 2 8 4 3 7 5 1 6 9 6 3 9 2 1 8 4 5 7 5 7 1 9 6 4 3 8 2 1 5 2 4 9 6 8 7 3 3 4 8 7 5 2 9 1 6 7 9 6 8 3 1 2 4 5 9 6 7 1 4 3 5 2 8 8 1 3 5 2 7 6 9 4 4 2 5 6 8 9 7 3 1
i.20
1 + i.20
*/ 1 + i.20