## Introduction

One of the requirements to writing and debugging code is to understand how to read the language in the first place. This applies to any language including human languages. If you can’t read English the following will be hard to understand.

### Case Study

I was recently reading a document written by Roger Hui and saw the expression

↑{(0∘,+,∘0)⍣⍵,1}¨∘⍳

that made me wonder how to explain how to parse an expression like this.

It is supposed to be read right-to-left but operators interfere with this technique and now with trains we need to revisit this.

This expression is a 2-train (called an Atop), a function made of 2 functions juxtaposed.

┌───┬──────────────────────┐ │ ↑ │ {(0∘,+,∘0)⍣⍵,1}¨ ∘ ⍳ │ └───┴──────────────────────┘

Dyalog V.14 introduced trains.

A train is a series of functions lined up one after the other IN ISOLATION as in `(+÷×!-)`

, a train of 5 functions. The functions can be primitives, derived, composed, Dfns, other trains and even user defined traditional functions but they must be in isolation. In isolation means the functions are isolated from data. In `(+÷×!-)5`

the 5-function train is isolated from the 5, whereas in `+÷×!- 5`

it is not.

A two-train function is called an Atop. A three-train function is called a Fork. More than three function trains are reduced to two or three by considering the three rightmost functions (a Fork) as a function.

Let’s see why this expression is a train

Reading from right to left:

- The first symbol is
*Iota*, the Index generator function. - The second symbol is
*Jot*, the*Compose*operator.*Compose*accepts two operands, each may be a function or an array. - The third symbol is
*Dieresis*, another operator named*Each*, which means the left operand to*Compose*is not an array. It is a derived function, made of another function which must be bound to*Each*for*Compose*to work. - The fourth symbol is right brace
`}`

which marks the end of a D-fn. Scanning left until we reach its matching`{`

we get the function`{(0∘,+,∘0)⍣⍵,1}¨∘⍳`

- The next symbol is a function,
`↑`

, and it is not bound to`{`

and the entire line, except for the leftmost character*Up Arrow*, is the rightmost function of the Atop.

The only symbol left, *Up Arrow* `↑`

, is the other function and this line constitutes the definition of a two-train function, an Atop. This can be seen as

P1← ↑ P2← {(0∘,+,∘0)⍣⍵,1}¨ ∘ ⍳ P ← P1 P2

OK, but what does it do?

Let’s have a better look at `P2`

.

This is a Dfn bound to *Each* as left operand to *Compose* and with *Iota* as the right operand.`P2`

‘s argument (`n`

) is given to *Iota*, generating a series of `n`

integers each of which is fed to the Dfn one by one (because of *Each*) making effectively `n`

separate calls to the Dfn.

Let’s have a look at that Dfn in more details:

Reading from the right inside the Dfn ‘`,`

’ is the first function encountered but the object to its left is bound to the operator *Power* (`⍣`

) so ‘`,`

’ is monadic, it is the *Ravel* function. It turns the scalar 1 to its right into a 1-element vector containing the number 1.

*Power* only accepts functions as left operand so what’s in parentheses to its left better be a function or we’ll get a SYNTAX ERROR.

What’s within parentheses and omega constitute the function applied to `,1`

. In the Dfn `{(0∘,+,∘0)⍣⍵ ,1}`

the function `(0∘,+,∘0)`

is applied *omega* times to `,1`

. We could rewrite `P2`

like this:

F← (0∘,+,∘0) ⋄ P2← { F⍣⍵ ,1}¨ ∘ ⍳

Let’s have a look at `F`

more closely. It’s a Fork. This is the first function:

┌───┐ 0∘, + │,∘0│ └───┘

it is ‘`,`

’ bound to 0 via the *Compose* operator. It is a function that concatenates 0 **after** its argument.

Operators bind their arguments **before** the functions can make up trains. This is a rule which did not exist before because trains of functions did not exist then.

It is preceded by another function *Plus* which is not bound to anything:

┌─┐ 0∘, │+│ ,∘0 └─┘

This in turn is preceded by another function made of 0 bound to ‘`,`

’ via the *Compose* operator. It is a function that concatenates 0 **before** its argument.

┌───┐ │0∘,│ + ,∘0 └───┘

The function is a three-function train. In this case it is a Fork.

┌───┬─┬───┐ F←│0∘,│+│,∘0│ └───┴─┴───┘

Applying this function once to `,1`

(0∘, + ,∘0 ) ,1 1 1

Is the same as

(0∘, ,1) + (,∘0 ,1) 1 1

or

0 1 + 1 0 1 1

Applying this function twice to `,1`

F F ,1 ⍝ or F⍣2 ,1

Is the same as `F 1 1,`

or the same as

(0∘, 1 1) + (,∘0) 1 1

or

0 1 1 + 1 1 0 1 2 1

Applying this function thrice to `,1`

is

F F F ,1 ⍝ or F⍣3 ,1

Is the same as `F 1 2 1,`

or the same as

(0∘, 1 2 1) + (,∘0) 1 2 1

or

0 1 2 1 + 1 2 1 0 1 3 3 1

Going back to the original function:

P ← ↑ {(0∘,+,∘0)⍣⍵,1}¨ ∘ ⍳

This is a train of two functions. Which again can be seen as

P ← P1 P2

P2 applied to an integer e.g. 4, **in origin 0,** is

{(0∘,+,∘0)⍣⍵,1}¨ ∘ ⍳4

or

{(0∘,+,∘0)⍣⍵,1}¨ 0 1 2 3

or

(,1) (1 1) (1 2 1) (1 3 3 1)

Applying `P1(↑)`

, **with ⎕ML 1**, to this array results in

1 0 0 0 1 1 0 0 1 2 1 0 1 3 3 1

And going back to the original function:

P← ↑ {(0∘,+,∘0)⍣⍵,1}¨ ∘ ⍳ P 4 1 0 0 0 1 1 0 0 1 2 1 0 1 3 3 1

It generates the Pascal Triangle.

## Conclusion

This kind of code will appear more and more often in the future. Even if we do not intend to use all the new features yet we need to be able to read them and understand what it means. APL is evolving all the time, just like any other language. English, Russian, Mandarin weren’t spoken the same way 300 years ago and they won’t be the same 300 years hence. APL wasn’t the same 30 years ago; it WILL be different in the future. We need to adapt.

## Note

You can “see” this article in a video here:

youtu.be/kt4lMZbn-so or search for APLtrainer in YouTube to find it.