The World Around Us: back to words with J
Contents
Isaac Asimov
The most exciting phrase to hear in science, the one that heralds new discoveries, is not “Eureka!” (I’ve found it!), but “That’s funny…”
Sometimes everybody wants to get off the beaten track and see the world. See how many exciting discoveries are waiting for you there.
I want to bring your attention to a language, which changed the vision of some things for me. This language is J.
J is an array programming language; it is also functional and even objectoriented. And extremely concise. If you ever called F# ‘cryptic’ because of its operators or started to hate a Scala dev writing /:
instead of fold
– stop right here, because this language is definitely not for you.
If you have a suspicion that J is for aliens, relax – it’s just different. In terms of grammar J is literally closer to English than C or Java. Who said ‘token’? It’s time to remember the good old ‘word’. Functions are verbs, objects – nouns, statements  sentences etc.
Now let’s experiment!
It’s really funny, that whys start with:
J is a very rich language. You could study and use it for years, and still consider yourself a beginner.
You’ll get it later =).
But what trapped me for a weekend? I suspect it’s all about unusual code and the new ways of thinking. Maybe something is wrong with me, but J is really fun to write and read! (though the latter requires more effort…)
Some operators
*:
 square
/
 ‘insert’, f/ x y z = x f y f z
%
 division
_
 unary minus
>:
 increment
#
 ‘tally’, the number of elements
@
 ‘atop’, composition
@.
– ‘agenda’/switch conjunction
=:
 assignment
`
 ‘tie’ conjunction
.
– reverse the order
:
 transpose matrix
+/ .*
 matrix multiplication
Conjunctions
First of all, note, that the rightmost function is applied first, so 3*2+1 = 3*(2+1) = 9
. How do we calculate, say, the sum of squares?
Square numbers (output is provided in comments starting with NB.):


J has a special operator /
, called ‘insert’, I prefer to think about it as ‘reduce’:


The equivalent is 1 + 2 + 3
.
So the sum of squares can be written as


Conjunction &
allows to ‘fix’ the left or right argument:


Monads and Dyads
Those who like the forbidden Mword may be confused. But APLstyle definition is actually older: monad is a function taking a single argument on the right (like *:
above). Dyad takes two arguments, on the left and on the right (40 + 2
).
Hooks and Forks
When two verbs come together, we call it a hook:
(f g) y = y f (g y)
Let’s normalize the list of elements so that their sum is equal to 1 (note, that division is denoted with %
). See the naïve variants and a hook:


Three verbs form a fork:
(f g h) y = (f y) g (h y)
My favorite fork example is mean:


The same as


Gerund
The things are getting even more interesting: meet a gerund (the result of `
)! The sense is similar to English: derived from a verb, but functions as a noun.


We can choose one of the ‘boxes’ with switch conjunction @.
:


Look at the abs implementation:


Gerund can be used together with ‘insert’, e.g. the following statement sentence is equivalent to (50 * 2 % 100)
:


More Verbs!
#.
– dyad ‘base’ or monad ‘from base 2’


[
and ]
– ‘same’, id or argument


+/\
– running sum (the same works for * etc)


{.
 take (n {. L
)


}.
 drop (n }. L
)


{
 fetch


/:
 sorting


Remember fork, id and fetch?


q:
 prime factors


p:
 generate nth prime


sum 100 primes:


Modelling Transitions
Having several states and markovprocess like transitions probabilities, what is the probability of one of these states at some time? Credit rating migrations can be taken as an example of such transitions.
So we define matrix and initial state probabilities:


At time y
the result is T^y
(x u^:n y
is equivalent to x u x u …(n times) y
). What is the probability of state 3?


The first two options transpose matrix, select the column with index 2 and calculate dotproduct with x. The last one uses matrix multiplication verb.
Present Value
Given the stream of cashflows and rate (in %), we want to calculate PV.
Cashflows: 100 50
Rate: 5%
PV = 100 + 50 / (1 + 5%) = 147.61905
Splitting by steps:
 transform %


 compute discount factor


 reverse cashflows list and sum the discounted values
(50 * df^1 + 100 * df^0)
:


 combine everything


1: pv =: %@>:@(] % 100"_) #. .@[ 2: 100 50 pv 5 147.619
Bonus
If you’re still able to follow this post, here’s a couple of references:
 J Reference Card (2 pages to your rescue);
 financial phrases;
 essay on piano tuning;
 linear recurrences and matrix powers;
 simplex method in J.
Happy crazy coding!
Author Natallie
LastMod 20130825