The World Around Us: back to words with J

Leave a comment

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…”
(Isaac Asimov)

[This blog was moved here]

Sometimes everybody wants to get off the beaten track and see the world. See how many exciting discoveries are waiting for you there.
J Logo

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 object-oriented. 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!

– J download is here;
– Getting started materials;
– Why J page.

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 (command output is green):

 1: *: 1 2 3
    1 4 9

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

 1: +/ 1 2 3
    6

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

 1: +/ *: 1 2 3
    14

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

 1: (^&2) 1 2 3
    1 4 9
 2: (2&^) 1 2 3
    2 4 8

Monads and Dyads

Those who like the forbidden M-word may be confused. But APL-style 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:

 1: 1 2 5 % (1 + 2 + 5)
 2: 1 2 5 % +/ 1 2 5
 3: (% +/) 1 2 5
    0.125 0.25 0.625

Three verbs form a fork:

(f g h) y = (f y) g (h y)

My favorite fork example is mean:

 1: (+/ % #) 1 2 3 4
    2.5

The same as

 1: (+/ 1 2 3 4) % (# 1 2 3 4)
 2: +/ 1 2 3 4 % # 1 2 3 4

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.

 1: + ` -
    ┌─┬─┐
    │+│-│
    └─┴─┘

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

 1: + ` - @. 0
    +
 2: + ` - @. 1
    -

Look at the abs implementation:

 1: abs =: + ` - @. (< & 0)
 2: abs 42
    42
 3: abs _42
    42

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

 1: * ` % / 50 2 100
    1

More Verbs!

#. – dyad ‘base’ or monad ‘from base 2’

 1: #. 1 0 0 1   
    9  
 2: 3 #. 2 1   
    7

[ and ] – ‘same’, id or argument

 1: [ 2   
    2
 2: 1 [ 2   
    1  
 3: ] 2   
    2  
 4: 1 [ 2   
    2

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

 1: +/\ 2 3 4   
    2 5 9
 2: acc =: /\
 3: + acc 2 3 4
    2 5 9
 4: * acc 2 3 4
    2 6 24

{. – take (n {. L)

 1: 2 {. 3 4 5   
    3 4

}. – drop (n }. L)

 1: 2 }. 3 4 5   
    5

{ – fetch

 1: 1 { 3 4 5 6   
    4
 2: _1 { 3 4 5 6   
    6

/: – sorting

 1: /: 10 2 5 3   
    1 3 2 0

Remember fork, id and fetch?

 1: (/: { ]) 10 2 5 3   
    2 3 5 10

q: – prime factors

 1: q: 20   
    2 2 5

p: – generate nth prime

 1: p: 3   
    7

sum 100 primes:

 1: +/ p: i. 100   
    24133

Modelling Transitions

Having several states and markov-process 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:

 1: T =: 3 3 $ 0.6 0.3 0.1 0.1 0.5 0.4 0 0.1 0.9
 2: x =: 0.3 0.2 0.5

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?

 1: T3 =: T +/ .*^:2 T
 2: +/ x * (2 {|: T3)
    0.6668
 3: +/ x * [ 2 {|: T3
    0.6668
 4:  2 { x +/ .* T3
    0.6668

The first two options transpose matrix, select the column with index 2 and calculate dot-product 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 %

 1: pv =: >:@(] % 100"_)
 2: pv 5
    1.05

– compute discount factor

 1: pv =: %@>:@(] % 100"_)
 2: pv 5
    0.952381
 3: 1 % 1.05
    0.952381

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

 1: |. 100 50
    50 100
 2: 0.952381 #. |. 100 50
    147.619

– 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!