]box on -style=max -trains=tree -fns=on
┌→─────────────────────────────────────┐ │Was ON -style=max -trains=tree -fns=on│ └──────────────────────────────────────┘
Jeremy Howard
July 5, 2022
This series will explore all the different glyphs in Dyalog APL. Wherever possible examples of a glyph will exist for each glyph that do not use other glyphs. The purpose of this post is to create documentation for glyphs that are helpful for beginners getting started.
To get help on a glyph, such as ≠
, type:
]Help ≠
To get more detailed “pictures” of arrays and tacit functions type:
]box on -style=max -trains=tree -fns=on
┌→─────────────────────────────────────┐ │Was ON -style=max -trains=tree -fns=on│ └──────────────────────────────────────┘
This first notebook in the series covers the basic objects.
Numbers are represented as they are in many other languages. Integers, negative numbers, and decimals can be created.
Note: Notice that
¯
is a high bar and not the symbol normally used in many other programming languages such as python
1
1
¯1
¯1
1.5
1.5
Complex numbers can be created using j
to represent the i
.
0j4
0J4
3j4
3J4
3j4
means 3+4i
.
4j0
4
4j0
means 4+0i
, which is just the real number 4
¯5j¯6
¯5J¯6
The syntax for creating a rank-1 array is to separate elements with spaces.
2 3 1
┌→────┐ │2 3 1│ └~────┘
2 ¯3 1
┌→─────┐ │2 ¯3 1│ └~─────┘
0j4 ¯5j¯6
┌→────────┐ │0J4 ¯5J¯6│ └~────────┘
To nest arrays we now need to use parenthesis. The parenthesis are dictating the order of operations (it’s not array specific syntax).
1 2 3 4 (1 2)
┌→──────────────┐ │ ┌→──┐ │ │ 1 2 3 4 │1 2│ │ │ └~──┘ │ └∊──────────────┘
(1 2)(3 4)
┌→────────────┐ │ ┌→──┐ ┌→──┐ │ │ │1 2│ │3 4│ │ │ └~──┘ └~──┘ │ └∊────────────┘
(1 2)(3 4)5
┌→──────────────┐ │ ┌→──┐ ┌→──┐ │ │ │1 2│ │3 4│ 5 │ │ └~──┘ └~──┘ │ └∊──────────────┘
⍝
tells apl that anything after this character on that line should be ignored and not executed. Great for writing yourself notes for what pieces of code do.
⍝ This is a comment and doesn't do anything
1 2 3 ⍝ This is a comment after some code
┌→────┐ │1 2 3│ └~────┘
-
(Minus sign; Bar)-
(Negate)Negate multiplies each element by ¯1
. Positive numbers become negative and negative numbers become positive.
- 4
¯4
- ¯4
4
- 4 2 0 ¯3 ¯5
┌→──────────┐ │¯4 ¯2 0 3 5│ └~──────────┘
¯4 2 0 ¯3 ¯5
┌→───────────┐ │¯4 2 0 ¯3 ¯5│ └~───────────┘
-
(Minus; subtract)3-2
1
Subtracting happens element-wise.
3 2 1 - 4 5 1
┌→──────┐ │¯1 ¯3 0│ └~──────┘
APL will broadcast to make element-wise subtraction possible
3 2 1 - 1
┌→────┐ │2 1 0│ └~────┘
1 - 3 2 1
┌→──────┐ │¯2 ¯1 0│ └~──────┘
+
(Plus sign)+
(Conjugate)+ 1.2
1.2
+ ¯5j¯6
¯5J6
¯5j¯6
means ¯5+¯6i
. Conjugate negates the imaginary component of complex numbers.
+ 1.2 0j4 ¯5j¯6
┌→────────────┐ │1.2 0J¯4 ¯5J6│ └~────────────┘
+
(Plus)Plus works element-wise just like minus.
3+2
5
3 2 1 + 4 5 1
┌→────┐ │7 7 2│ └~────┘
3 2 1 + 1
┌→────┐ │4 3 2│ └~────┘
1 + 3 2 1
┌→────┐ │4 3 2│ └~────┘
|
(Stile;Vertical Bar)|
(Magnitude)|3 ¯3 3j4
┌→────┐ │3 3 5│ └~────┘
3j4
means 3+4i
, which has a magnitude of 5 (because (3×3)+(4×4)=(5×5)).
|
(Residue;Modulus)Residue;Modulus works element-wise.
2 10 2 | 7 13 8
┌→────┐ │1 3 0│ └~────┘
Negative numbers can seem a bit confusing at first. Here is an article that can help you understand modulo with negative numbers.
2 10 ¯2.5 | 7 ¯13 8
┌→─────┐ │1 7 ¯2│ └~─────┘
10 10 ¯10 ¯10 | 13 ¯13 13 ¯13
┌→────────┐ │3 7 ¯7 ¯3│ └~────────┘
÷
(Divide sign)÷
(Reciprocol)Reciprocal is division where 1 is the left argument.
÷ 3
is equivalent to 1 ÷ 3
÷ ¯2
is equivalent to 1 ÷ ¯2
÷ 3j4
is equivalent to 1 ÷ 3j4
÷ 3 ¯2 3j4
┌→───────────────────────────┐ │0.3333333333 ¯0.5 0.12J¯0.16│ └~───────────────────────────┘
÷
(Divided by)Divided by does element-wise division
3÷2
1.5
3÷2 2.5 ¯1
┌→─────────┐ │1.5 1.2 ¯3│ └~─────────┘
3 2 1÷2 2.5 ¯1
┌→─────────┐ │1.5 0.8 ¯1│ └~─────────┘
×
(Times sign)×
(Direction)For real numbers: 1 for positive numbers, ¯1 for negative numbers, 0 for 0.
× 3.1 ¯2 0 3j4
┌→─────────────┐ │1 ¯1 0 0.6J0.8│ └~─────────────┘
Complex numbers are divided by their magnitude. 0.6j0.8
represents a vector in the same direction as 3j4
, but with a magnitude of 1, since it’s 3j4÷5
.
3j4÷(|3j4)
0.6J0.8
÷∘|⍨3j4
0.6J0.8
÷∘|⍨
⍨ ┌─┘ ∘ ┌┴┐ ÷ |
×
(Times)Element-wise multiplication
3×2
6
3×2 2.5 ¯1
┌→───────┐ │6 7.5 ¯3│ └~───────┘
3 2 1×2 2.5 ¯1
┌→─────┐ │6 5 ¯1│ └~─────┘
*
(Star)*
(Exponential)Exponential takes e
to the power of the input argument. * 1
is equal to e
* 0 1 2
┌→────────────────────────┐ │1 2.718281828 7.389056099│ └~────────────────────────┘
*
(Power)Power takes the left arguement and puts it to the power of the right arguement. Power is applied elementwise.
49 5 ¯4 * 0.5 2 0.5
┌→───────┐ │7 25 0J2│ └~───────┘
!
(Exclamation mark)!
(factorial)5 Factorial, or !5
is equal to 5×4×3×2×1
.
!5
120
!1.5 ⍝ gamma(1.5+1)
1.329340388
!
(Binomial)Binomial can be defined using factorial: X!Y ←→ (!Y)÷(!X)×!Y-X
. R is the number of selections of X things from Y things.
0 1 2 3 4 5 ! 5
┌→────────────┐ │1 5 10 10 5 1│ └~────────────┘
?
(Question mark)?
(Roll)Gives a random integer between 1 and the input argument or, in the case of 0, a random non-integer between 0 and 1
? 6 6 6 6 6
┌→────────┐ │4 3 4 2 1│ └~────────┘
? 0 0
┌→────────────────────────┐ │0.5456603511 0.3390443517│ └~────────────────────────┘
?
(Deal)Generates left argument number of numbers between 1 and the right argument. So 13 ? 52
will give 13 numbers between 1 and 52. Deal does sampling without replacement, meaning the same number will not show up multiple times.
13 ? 52
┌→──────────────────────────────────┐ │51 50 26 10 40 4 34 2 38 8 27 42 44│ └~──────────────────────────────────┘
○
(Circle)○
(Pi Times)Multiplies pi
times the input argument.
○ 0 1 2
┌→────────────────────────┐ │0 3.141592654 6.283185307│ └~────────────────────────┘
○
(Circular Function - Trig)For table of stuff ᴏ
can do, see the docs. Theleft argument selects function(s) to apply. E.g 1
gives Sine ⍵
, and and 2
is Cos.
0 1 ○ 0
┌→──┐ │1 0│ └~──┘
⍟
(Logarithm; Circle Star)⍟
(Natural Log)The natural logarithm of a number is its logarithm to the base of the mathematical constant e
⍟ 1 2 3 (*1)
┌→───────────────────────────┐ │0 0.6931471806 1.098612289 1│ └~───────────────────────────┘
⍟
(Log)Calculates the log. 2⍟32
is equal to log2(32)
2 10 ⍟ 32 1000
┌→──┐ │5 3│ └~──┘
Function precedence in APL is always right to left, evaluating parentheses when encountered. This means 3×2+1
does the addition first before the multiplication because addition is further right. You could change the order of operations by using parenthesis, (3×2)+1
, or reordering it to 1+3×2
.
3×2+1
9
Before functions are applied, vectors are created. 1 2 3×2
creates the vector 1 2 3
first, then applies functions right to left. The below code cell could be rewritten as (1 2 3)×2
, but since the parenthesis is redundant it is often best practice to leave it off. This is often referred to as stranding having a higher binding strength than function applications.
1 2 3×2
┌→────┐ │2 4 6│ └~────┘
1 2 3×2+1
┌→────┐ │3 6 9│ └~────┘
1 2 3×2+2 4 6
┌→──────┐ │4 12 24│ └~──────┘
3 ¯5 + 4
┌→───┐ │7 ¯1│ └~───┘
The next example follows the same precedence. ÷3
is done first (reciprocal 3).
8*÷3
2
The left arrow assigns to variables. a←3
is 3 is assigned to a.
a←3
a
3
There’re 2 interesting things in the next example:
⎕←a←3
3
b←3 4
b
┌→──┐ │3 4│ └~──┘
Single argument functions (monadic functions) in APL have the argument ⍵
, which always is input to the right of the function. You cannot change the name of the argument. Enclosing something in curly braces is the syntax for function definition.
{⍵×2} 4
8
f ← {⍵×2}
f 4
8
Dual argument function (dyadic functions) in APL have an additional argument ⍺
, which is input to the left of the function.
g ← {⍵×2+⍺}
3 g 4
20
f ← {⍵×2}
h ← {2 + f ⍵}
h 4
10
Statement separator can be used to perform a computation in multiple steps. In the below example a ← ⍵×2
is evaluated, then 2 + a
is evaluated and returned.
f ← {a ← ⍵×2 ⋄ 2 + a}
f 4
10
f←{a←1 ⋄ 2 ⋄ 3} ⍝ First non-assignment is the result of the function
f 2
2
A guard expression allows you to specify a condition for a result.
{⍵>1:1 ⋄ ⍵}
says if ⍵
is greater than 1, then 1 else ⍵
fact←{⍵>1:1 ⋄ ⍵}
Other conditionals and more complex expressions can be used in guard expressions
fact1←{⍵≤1:1 ⋄ ⍵×fact ⍵-1 }
fact 1
1
fact 5
1
Recursion can be simplified using ∇
.
{⍵≤1:1 ⋄ ⍵×∇ ⍵-1} 5
120
This accomplishes the same thing as the function calling itself more explicitly
fact1 ← {⍵≤1:1 ⋄ ⍵×fact1 ⍵-1 }
fact2 ← {⍵≤1:1 ⋄ ⍵×∇ ⍵-1}
(fact1 1) = (fact2 1)
(fact1 5) = (fact2 5)
1
1
{⍵≤1:1 ⋄ ⍵×∇ ⍵-1} 5
120
fact ← {⍵≤1:1 ⋄ ⍵×∇ ⍵-1}
fact 1
1
fact 5
120
(a b) ← 3 4
a
3
⍴
(rho)⍴
(reshape)By default a series of numbers creates a 1 dimensional vector
⎕ ← 1 2 3 4 5 6
┌→──────────┐ │1 2 3 4 5 6│ └~──────────┘
The ⍴
function can reshape it into the specified shape.
a ← 1 2 3 4 5 6
⎕←mat←2 3 ⍴ a
┌→────┐ ↓1 2 3│ │4 5 6│ └~────┘
a ← 1 2 3 4 5 6
3 2 ⍴ a
┌→──┐ ↓1 2│ │3 4│ │5 6│ └~──┘
a ← 1 2 3 4 5 6
1 6 ⍴ a
┌→──────────┐ ↓1 2 3 4 5 6│ └~──────────┘
Reshape will broadcast the original vector as needed to create the desired shape.
a ← 1 2 3 4 5 6
⎕←c←2 2 3 ⍴ a
┌┌→────┐ ↓↓1 2 3│ ││4 5 6│ ││ │ ││1 2 3│ ││4 5 6│ └└~────┘
2 3 ⍴ 1
┌→────┐ ↓1 1 1│ │1 1 1│ └~────┘
⍴
(shape of)The mondadic ⍴
tells you what the shape is.
a ← 1 2 3 4 5 6
⍴a
┌→┐ │6│ └~┘
mat←2 3 ⍴ a
⍴mat
┌→──┐ │2 3│ └~──┘
The shape of a scalar is the empty vector.
⍴3
┌⊖┐ │0│ └~┘
⍬
┌⊖┐ │0│ └~┘
⍴⍬
┌→┐ │0│ └~┘
mat←2 3 ⍴ a
⍴⍴mat
┌→┐ │2│ └~┘
mat←2 3 ⍴ a
⍴⍴⍴mat
┌→┐ │1│ └~┘
c←2 2 3 ⍴ a
⍴c
┌→────┐ │2 2 3│ └~────┘
c←2 2 3 ⍴ a
⍴⍴⍴c
┌→┐ │1│ └~┘
The boxes around the numbers have special meanings that are useful. The Display Conventions section covers the special meanings (6.4.1 in the Mastering Dyalog APL book). For convenience we have put the text of that section below.
The upper-left corner of the box provides information about the shape of the displayed value:
The bottom-left corner of the box provides information about the contents of the array:
A series of characters creates a character vector whose length is the number of characters in it
'ACF'
┌→──┐ │ACF│ └───┘
⍴'ACF'
┌→┐ │3│ └~┘
'A' 'C' 'F'
┌→──┐ │ACF│ └───┘
A single character is a scalar, and like other scalars has an empty shape.
⍴'y'
┌⊖┐ │0│ └~┘
⍴'your boat'
┌→┐ │9│ └~┘
1 2 3 4 'a'
┌→────────┐ │1 2 3 4 a│ └+────────┘
Because a series of strings is a vector, putting it in another array creates a nested array.
1 2 3 4 'ab'
┌→─────────────┐ │ ┌→─┐ │ │ 1 2 3 4 │ab│ │ │ └──┘ │ └∊─────────────┘
(1 2)(3 4)'ab'
┌→─────────────────┐ │ ┌→──┐ ┌→──┐ ┌→─┐ │ │ │1 2│ │3 4│ │ab│ │ │ └~──┘ └~──┘ └──┘ │ └∊─────────────────┘
There is a pre-defined variable that gives all the letters of the alphabet provided for convenience.
⎕A
┌→─────────────────────────┐ │ABCDEFGHIJKLMNOPQRSTUVWXYZ│ └──────────────────────────┘