⍴⌽⊖⍉⍎⍕#

Reshape #

We’ve met ⍴ (Greek Rho) in passing before. Let’s cover it in more depth. is maybe the most fundamental function in an array language, as it allows the formation of multi-dimensional (high-rank) arrays. Note that is not actually the Greek Rho in Unicode. Dyalog APL only uses the special Unicode APL Rho.

The Greek letter Rho is has the sound of the letter R, and stands for reshape. The right argument of is used in ravel order to fill an array with the dimensions given by the left argument. The left argument must therefore be a vector (list) of dimension lengths (although for ease of use, we do allow a scalar instead of a one-element vector). Another way to look at it is that the left argument of is the index of the last element in the resulting array (if you stick to the default ⎕IO of 1). If you omit the shape (left argument) then the current shape is returned.

3'a'
3'ab'
3'abcd'
2 3'abc'
aaa
aba
abc
abc
abc

That’s two rows and three columns. The order of the left argument is the number of major cells first and of “leaf” cells last.

3 4 5∘.+10 20 30 40
3 4 5∘.+10 20 30 40
13 23 33 43
14 24 34 44
15 25 35 45
3 4

A scalar doesn’t have any dimensions, so the corresponding left argument is (or 0⍴0):

3 4 5∘.+10 20 30 40
13

If one or more dimensions are 0, then the array doesn’t have any elements, but it is still there. If it has rank 2 or higher, then it has an empty default display. If an array has no elements, then will uses its prototype to fill any array it needs to form:

2 3
0 0 0
0 0 0

Recall that is just 0⍴0 so it being simple and numeric, its prototype is 0.

Reverse #

Monadic is reverse. It reverses the leaf rank-1 sub-arrays of an array. For a matrix, it means reversing each row:

2 4⍴⍳8
2 4⍴⍳8
1 2 3 4
5 6 7 8
4 3 2 1
8 7 6 5

For a vector, it simply means reversing the vector:

⎕A
⎕A
ABCDEFGHIJKLMNOPQRSTUVWXYZ
ZYXWVUTSRQPONMLKJIHGFEDCBA

Of course, it doesn’t affect scalars.

Reverse first #

has a sibling, just like / and \ have and , namely reverse first, , which I usually call “Flip”. reverses the order of major cells, which for a matrix means reversing the order of the rows, i.e. flipping it upside down:

2 4⍴⍳8
5 6 7 8
1 2 3 4

For vectors, it is the same as and again it does nothing to scalars. For a 3D array, it reverses the order of layers:

4 2 3⎕A
4 2 3⎕A
ABC
DEF

GHI
JKL

MNO
PQR

STU
VWX
STU
VWX

MNO
PQR

GHI
JKL

ABC
DEF

Dyadic and do rotations instead of reversals:

3⎕A
14 2 3⎕A
DEFGHIJKLMNOPQRSTUVWXYZABC
GHI
JKL

MNO
PQR

STU
VWX

ABC
DEF

Negative rotation amounts just rotate to the other way:

¯3⎕A
XYZABCDEFGHIJKLMNOPQRSTUVW

Here is a cool feature of and : If you give them a vector of rotation amounts, they get distributed on the relevant cells:

3 4⎕A
1 0 23 4⎕A
1 0 ¯1 03 4⎕A
ABCD
EFGH
IJKL
BCDA
EFGH
KLIJ
EBKD
IFCH
AJGL

Transpose #

and also have a cousin named (Transpose). The monadic function does not reverse the major cells or the rank 1 cells, but rather reverses the order of the indices. For matrices this is normal transposing:

3 4⎕A
3 4⎕A
ABCD
EFGH
IJKL
AEI
BFJ
CGK
DHL

For arrays of rank higher than 2 it helps to think of the shape as being reversed:

2 3 4⎕A
AM
EQ
IU

BN
FR
JV

CO
GS
KW

DP
HT
LX

If you look carefully, you can see that the runs like ABCD which originally spanned rows are now spanning layers. Look at the top left corner of each new layer. So, too, are the layers now spanning rows. Look how the top left of the layers, A and M are now next to each other in a row. Whilst the column AEI is still a column, because reversing the shape 2 3 4 (layers, rows, columns) gives 4 3 2 (columns, rows, layers) so the runs spanning rows are in the same position, still spanning rows.

Now you know how to reverse the order of axes, but what if you want an entirely new order? That’s what dyadic does. The left argument is the indices of the axes in the desired order. Therefore, if we reverse the indices of the rank, it is the same as monadic transpose:

3 2 12 3 4⎕A
AM
EQ
IU

BN
FR
JV

CO
GS
KW

DP
HT
LX

Now we can keep the layers and only reverse (i.e. transpose) columns/rows:

1 3 22 3 4⎕A
AEI
BFJ
CGK
DHL

MQU
NRV
OSW
PTX

Here is a very cool thing: You can duplicate indices in the left argument. If so, APL will merge the indicated axes, taking only the elements that have equal indices along those two axes. This is the diagonal or diagonal plane, or diagonal 3D array (!), etc.

3 4⎕A
1 13 4⎕A
1 1 12 3 4⎕A
1 1 22 3 4⎕A
ABCD
EFGH
IJKL
AFK
AR
ABCD
QRST

Here the layers and rows got merged, i.e. 1st row of 1st layer and 2nd row of 2nd layer, while the columns stayed as is.

1 2 12 3 4⎕A
AEI
NRV

Here we merged layers and columns, i.e. 1st column of 1st layer and second column of 2nd layer. Dyadic is pretty advanced and quite rarely used, but when you need it (and can figure out the correct left argument — experiment!) it is really handy.

Here’s an example. Given a multiplication table, what were the numbers that generated it?

3 39 6 12 6 4 8 12 8 16 ⍝ A multiplication table
 9 6 12
 6 4  8
12 8 16

In this case, the answer is 3 2 4:

∘.×3 2 4
 9 6 12
 6 4  8
12 8 16

We can ‘reverse engineer’ this by finding the square root of the diagonal elements:

1 13 39 6 12 6 4 8 12 8 16       ⍝ main diagonal
0.5*1 13 39 6 12 6 4 8 12 8 16
9 4 16
3 2 4

Execute #

Execute, , evaluates a string representing a line of APL. This can be any valid APL expression, including functions and multiple statements:

'2+3'
2('+')3
'a←2 ⋄ a←a+3 ⋄ a'
5
5
5

The result of is the result of the last statement, if that has a result. If it doesn’t (e.g. it is an empty statement or has a leading {}), then doesn’t have a result either. The result of can be a monadic operator:

('¨')'abc' 'defg'
3 4

has all the features of a line of APL. You can run your entire program from . Indeed, when a workspace is loaded, APL automatically does ⍎⎕LX to bootstrap your application. This is what causes the greeting message when you load a workspace like dfns.

Dyadic is exactly like the monadic, but executes the expression in the namespace named in the left argument.

0 0a'base'
ns⎕NS
ns.a'sub'
'a'
'ns''a'
base
sub

Here we first set a to 'base' in # (the root namespace), then we created the empty namespace ns, populated it there, then evaluated a here (in #) and then in ns. In other words, monadic is the same as dyadic but with the default left argument of ⎕THIS (this current namespace).

Nowadays, we usually “dot into” namespaces to evaluate there:

0 0a'base'
ns⎕NS
ns.a'sub'
'a'
ns.'a'
base
sub

Same as before, but here we used the “value” of inside ns instead of ’s value here.

Format #

Format, , is really quite simple. It returns a simple character vector or matrix which displays exactly as if its argument had been displayed:

]display 1 2 3 4   ⍝ numeric vector
1 2 3 4

]display 1 2 3 4  ⍝ convert to character vector
≢⍕1 2 3 4
┌→──────┐
│1 2 3 4│
└~──────┘
4
┌→──────┐
│1 2 3 4│
└───────┘
7

If you give a left argument, it will display numeric values with that many decimals, rounding 5 up:

42÷3    ⍝ character vector of 2÷3 rounded to 4 dp
41 2 3÷3
 0.6667
 0.3333 0.6667 1.0000

If you give it two values as left argument, it will use the first as “field width” and the second as the number of decimal places:

20 41 2 3÷3
              0.3333              0.6667              1.0000

You can also use twice as many elements on the left as there are leaf cells on the right, and it will pair each two on the left to each one on the right:

10 4 20 0 15 11 2 3÷3
    0.3333                   1            1.0