Iverson style array programming
- https://aplwiki.com/wiki/Iverson_notation
- Kenneth Iverson's notations
- APL grew out of this idea
—
- monadic: unary
- dyadic: binary
Remarks:
- Understanding the concept of ranks is very important in using APL.
- Array is (more?) to APL as table is to lua.
- APL evaluates expressions from right to left
*is exponentiation. Multiplication is×
General
- Comment: ⍝
- Indexing starts from index origin (
IO)
Constants
- e:
*1(ie, e1) - pi:
○1
Operators
| Symbol | Monadic | Dyadic |
|---|---|---|
| ¯ | ✓ | |
| × | ? | ✓ |
| ÷ | ✓ | ✓ |
| ρ | ? | ✓ |
| ι | ✓ | ? |
| ⊖ | ✓ | |
| ⌽ | ✓ | |
| ⍉ | ✓ | |
| ↓ | ✓ | |
| ↑ | ✓ | |
/ |
✓ | |
| ⌿ | ||
| ? | ✓ | |
| ⌈ | ✓ | |
| ⌊ | ✓ | |
| ○ | ✓ | ✓ |
* |
✓ | ✓ |
| ⍟ | ✓ | ✓ |
| ≢ | ✓ | ✓ |
| ∪ | ✓ | ✓ |
| ∩ | ✗ | ✓ |
| ⊢ | ✓ | ✗ |
Arithmetic
- ¯: unary negation
- ×: multiplication
- ÷ (dyadic): division
- ÷ (monadic): reciprocal
Reshape / shape (ρ )
https://aplwiki.com/wiki/Reshape
Two forms:
- Dyadic: Reshape an array.
- Monadic: Get shape of array
Dyadic examples:
> 2 4 ρ ⍳ 8
1 2 3 4
5 6 7 8
> 3 2 ρ ⍳ 6
1 2
3 4
5 6
> ⍝ Looks like truncation happens if shape doesn't fit
> 3 2 ρ ⍳ 8
1 2
3 4
5 6
Monadic example:
> ρ 2 4 ρ ⍳ 8
2 4
—
> 5 ⍴ 0
⍝ No output
> 5 ⍴ 0
0 0 0 0 0
> 2 5 ⍴ 0
0 0 0 0 0
0 0 0 0 0
Index generator (⍳)
https://aplwiki.com/wiki/Index_Generator
> ⍳ 9
1 2 3 4 5 6 7 8 9
> ⍝ Set index origin so that ⍳ starts from 0
> ⎕IO ← 0
> ⍳ 9
0 1 2 3 4 5 6 7 8
Reverse along first axis (⊖)
> ⊖ ⍳ 5
5 4 3 2 1
> ⍝ Rows got reversed
> ⊖ 3 2 ρ ⍳ 6
5 6
3 4
1 2
Reverse along last axis (⌽)
> ⌽ 3 2 ρ ⍳ 6
2 1
4 3
6 5
> 3 2 ρ ⍳ 6
1 2
3 4
5 6
> ⍝ Columns got reversed
> ⌽ 3 3 ρ ⍳ 9
3 2 1
6 5 4
9 8 7
Transpose (⍉)
> ⍝ Columns got reversed
> ⍉ 2 3 ρ ⍳ 6
1 4
2 5
3 6
Drop (↓)
Drop first n elements of an array.
> 1 ↓ 1 2 3 4 5 6 7
2 3 4 5 6 7
> 2 ↓ 1 2 3 4 5 6 7
3 4 5 6 7
Take (↑)
Take first n elements of an array.
> 2 ↑ 1 2 3 4 5 6 7
1 2
> 4 ↑ 1 2 3 4 5 6 7
1 2 3 4
Replicate (/)
- Duplication.
- A dyadic operator.
> 2 / 3 4 5
3 3 4 4 5 5
> 1 / 3 4 5
3 4 5
> 3 / 3 4 5
3 3 3 4 4 4 5 5 5
> 2 / (3 4 5) (6 7)
3 4 5 3 4 5 6 7 6 7
Reduce along first axis (⌿)
> 2 4 ρ ι 8
1 2 3 4
5 6 7 8
> + ⌿ 2 4 ρ ι 8
6 8 10 12
First axis here is column-wise ??
Reduce along last axis (/)
> 2 4 ρ ι 8
1 2 3 4
5 6 7 8
> + / 2 4 ρ ι 8
10 26
Scan along first and last axis (⍀ and \)
> 2 4 ρ ι 8
1 2 3 4
5 6 7 8
> + \ 2 4 ρ ι 8
1 3 6 10
5 11 18 26
> + ⍀ 2 4 ρ ι 8
1 2 3 4
6 8 10 12
Factorial (!)
> !5
120
—
For an array, it's a map to all elements:
> 2 4 ρ ι 8
1 2 3 4
5 6 7 8
> ! 2 4 ρ ι 8
1 2 6 24
120 720 5040 40320
Depth (≡)
Nesting depth.
> ≡ 2 4 ρ ι 8
1
> ≡ ι 8
1
Roll (?)
? n selects a number randomly from the first n
numbers.
> ? 100
97
> ? 100
76
> ? 100
82
> ? 100
92
Maximum number is ω. Count of numbers is α:
> ? 10
7
> 3 ? 10
7 9 4
n must be greater than 0.
> ? 0
DOMAIN ERROR
?0
^
Random values within a range:
Vector of random floats between 0 and 1:
> ⍝ Vector of length 5
> (5 ? 100) ÷ 100
0.75 0.92 0.14 0.32 0.34
> ⍝ Vector of length 5
> (5 ? 1000) ÷ 100
0.5 9.35 0.17 0.05 3.92
3x3 matrix of random floats between 0 and 1:
> 3 3 ⍴ (9 ? 1000) ÷ 1000
0.837 0.427 0.169
0.671 0.094 0.801
0.72 0.888 0.492
Ceiling and floor (⌈ and ⌊)
Both are monadic.
> ⌈ 3.2
4
> ⌈ 3.5
4
> ⌈ 3
3
> ⌊ 3
3
> ⌊ 3.5
3
> ⌊ 2.9
2
Circle function (○)
- Monadic usage: multiply arg with pi
- Dyadic usage: left argument selects a trigonometric function
- Positive left argument: sin, cos, tan, etc
- Negative left argument: sinh, cosh, tanh, etc
- Left arg range: -12 to 12
- -7 to 7: circular functions
- Others: spherical functions
| x | Formula |
|---|---|
| 0 | π * y |
| 1 | sin(y) |
| 2 | cos(y) |
| 3 | tan(y) |
| 4 | arcsin(y) |
| 5 | arccos(y) |
| 6 | arctan(y) |
| 7 | π * y |
| -1 | sinh(y) |
| -2 | cosh(y) |
| -3 | tanh(y) |
| -4 | arsinh(y) |
| -5 | arcosh(y) |
| -6 | artanh(y) |
Exponential (*)
> ⍳ 8
1 2 3 4 5 6 7 8
> 2 * ⍳ 8
2 4 8 16 32 64 128 256
Default base is e.
> * ⍳ 8
2.718281828 7.389056099 20.08553692 54.59815003 148.4131591 403.4287935
1096.633158 2980.957987
log (⍟)
Default base is e:
> ⍟4
1.386294361
> ⍟2.717
0.9995283304
> ⍟2.71828
0.9999993273
Other bases:
> 10 ⍟ 10000
4
> 2 ⍟ 2048
11
≢
Tally (monadic): Get first dimension of a matrix
> ⍝ 3D matrix > ≢ 2 3 4 ρ ι 24 2 > ⍝ 2D matrix > ≢ 3 8 ρ ι 24 3 > ⍝ Vector > ≢ ι 24 24 > ⍝ Scalar > ≢ 4 1Inequality (Dyadic): not-equal-to
> 3 ≢ 3 0 > 3 ≢ 4 1 > (1 2 3) ≢ (1 2 3) 0
∪
- Monadic: Take unique elements only
- Dyadic: Union of args, with 'duplicates of α in ω removed'
> ⍝ Monadic
> ∪ 1 2 3 3 3 4 5
1 2 3 4 5
> ⍝ Dyadic
> 1 2 3 3 4 ∪ 4 5
1 2 3 3 4 5
Intersection (∩)
- No monadic version
> 1 2 3 3 ∩ 4 5 2 1
1 2
Right/Identity (⊢)
- Monadic: Returns its argument unchanged
- Dyadic: Return right argument
> ⊢ 3 2
3 2
> 2 ⊢ 3 2
3 2
This operator is same as ⎕←ω.
Left/hide (⊢)
- Monadic: ??
- Dyadic: Return left argument
> 1 5 6 ⊣ 2 3
1 5 6
> ⊣ 2 3
⊣ 2 3
Axis
- Axes are dimensions along which the array is organized
- Rank of an array = number of axes
More
- ≢ (monadic): tally. Number of major cells in an array. Like len() of python
- ≡ (monadic): depth. ie, maximum level of (array) nesting
- Depth and rank aren't same
- ⍤: rank
- ⊢: ??
Examples
> n ← 5 6 7
> n + 2
7 8 9
> +/n
18
> -/n
> ⍝ 5 - (6 - 7)
6
> ×/n
210
> */n
> ⍝ Because * is exponentiation
> ⍝ 5^(6^7) is quite a large number (a 195667-digit number)
∞
emacs
emacs: gnu-apl mode
- https://github.com/lokedhs/gnu-apl-mode
- Activate with
M-x gnu-apl-mode - Shift to APL symbol keyboard by holding super key (ie, 'windows
key')
- There are other ways like the APL-Z input method.
User defined functions
- Delimited by ∇ and ∇ (del symbol)
Format:
∇ result ← fun_name arg_name
⍝ body
result ← expression
∇
Examples
Monadic:
∇ double ← square x
double ← x × x
∇
> square 3
9
Dyadic:
∇ sum ← x add y
sum ← x + y
∇
> 3 add 5
8
Niladic (no args):
Cannot have more than 2 args, but can use an array arg to get around that.
∇ result ← sigmoid x
result ← 1 ÷ 1 + *-x
∇
dfn
- Pronunciation: deefns
- Compact local functions, possibly anonymous
- Support in gnu-apl limited ??
- Terms:
- ⍺: left arg
- ⍵: right arg
- ∇: self reference (useful for recursion)
- 'A dfn is a sequence of expressions inside { and }, separated by ⋄ or newlines.'
- Return value: result of last evaluated expression
> cubed ← {⍵ × ⍵ × ⍵}
> cubed 3
27
> mult ← {α × ⍵}
> 4 mult 3
12
gnuapl
REPL:
- Exit repl:
)OFF - Run like: apl -s -f <file-name.apl>
- Workspace:
)CLEAR: clear workspace)LOAD myname: load saved workspace)DROP ws_name: delete a workspace)SAVE myname: save workspace)ERASE sym_name: delete a symbol from current workspace)COPY: copy some symbols)FNS: print names of functions defined in current workspace)OPS: print names of operators defined in current workspace)NMS: print all names defined in current workspace)VARS: print all user defined variables in current workspace
- Run script:
)IN myscript.apl - Load file:
data ← ⎕FIO[49] 'test_y.csv'
Functions
- ⎕FIO['fopen'] instead of the less intuitive ⎕FIO[3], or even
⎕FIO[fopen]
- https://www.gnu.org/software/apl/apl-intro.html#CH_3.4.14.13
- The 3 is an axis argument
- ⎕UCS: Universal Character Set
Can be used to convert between encodings for characters ?? Like character to integer unicode code point?? and the other way around
From https://www.gnu.org/software/apl/apl-intro.html#CH_3.4.3:
⍝ Unicode → integer conversion ⎕UCS 'APL ⍴⍪ $¥£€⍧ ÄÖÜäöüß' 65 80 76 32 9076 9066 32 36 165 163 8364 9063 32 196 214 220 228 246 252 223 ⍝ And back to Unicode ⎕UCS 65 80 76 32 9076 9066 32 36 165 163 8364 9063 32 196 214 220 22 8 246 252 223 APL ⍴⍪ $¥£€⍧ ÄÖÜäöüß
Editors
Emacs
Mode: gnu-apl-mode
—
- Interactive session:
M-x gnu-apl - Use APL-Z input method:
C-x RET C-\ - Show APL keyboard layout:
C-c C-korM-x gnu-apl-show-keyboard
- Symbol entry:
- Use super-key if WM doesn't hijack it
- Eg: Sup+i: ι
- Toggle input: C-\ APL-Z
- Escape:
. - Eg:
. ebecomes∈
- Escape:
- Use super-key if WM doesn't hijack it
vim
vim-apl: https://github.com/zoomlogo/vim-apl
Backtick is the prefix key by default:
`igivesι`$gives⍋`rgivesρ
Keyboard
Default keyboard is like (from here):
╔════╦════╦════╦════╦════╦════╦════╦════╦════╦════╦════╦════╦════╦═════════╗
║ ~ ║ !⌶ ║ @⍫ ║ #⍒ ║ $⍋ ║ %⌽ ║ ^⍉ ║ &⊖ ║ *⍟ ║ (⍱ ║ )⍲ ║ _! ║ +⌹ ║ ║
║ `◊ ║ 1¨ ║ 2¯ ║ 3< ║ 4≤ ║ 5= ║ 6≥ ║ 7> ║ 8≠ ║ 9∨ ║ 0∧ ║ -× ║ =÷ ║ BACKSP ║
╠════╩══╦═╩══╦═╩══╦═╩══╦═╩══╦═╩══╦═╩══╦═╩══╦═╩══╦═╩══╦═╩══╦═╩══╦═╩══╦══════╣
║ ║ Q ║ W⍹ ║ E⋸ ║ R ║ T⍨ ║ Y¥ ║ U ║ I⍸ ║ O⍥ ║ P⍣ ║ {⍞ ║ }⍬ ║ |⊣ ║
║ TAB ║ q? ║ w⍵ ║ e∈ ║ r⍴ ║ t∼ ║ y↑ ║ u↓ ║ i⍳ ║ o○ ║ p⋆ ║ [← ║ ]→ ║ \⊢ ║
╠═══════╩═╦══╩═╦══╩═╦══╩═╦══╩═╦══╩═╦══╩═╦══╩═╦══╩═╦══╩═╦══╩═╦══╩═╦══╩══════╣
║ (CAPS ║ A⍶ ║ S ║ D ║ F ║ G ║ H⍙ ║ J⍤ ║ K ║ L⌷ ║ :≡ ║ "≢ ║ ║
║ LOCK) ║ a⍺ ║ s⌈ ║ d⌊ ║ f_ ║ g∇ ║ h∆ ║ j∘ ║ k' ║ l⎕ ║ ;⍎ ║ '⍕ ║ RETURN ║
╠═════════╩═══╦╩═══╦╩═══╦╩═══╦╩═══╦╩═══╦╩═══╦╩═══╦╩═══╦╩═══╦╩═══╦╩═════════╣
║ ║ Z ║ Xχ ║ C¢ ║ V ║ B£ ║ N ║ M ║ <⍪ ║ >⍙ ║ ?⍠ ║ ║
║ SHIFT ║ z⊂ ║ x⊃ ║ c∩ ║ v∪ ║ b⊥ ║ n⊤ ║ m| ║ ,⍝ ║ .⍀ ║ /⌿ ║ SHIFT ║
╚═════════════╩════╩════╩════╩════╩════╩════╩════╩════╩════╩════╩══════════╝
(Depending on the font used, this may look different on different devices.)
Even more
- Game of life with apl: https://www.youtube.com/watch?v=a9xAKttWgP4
- ANN with apl: https://www.youtube.com/playlist?list=PLgTqamKi1MS3p-O0QAgjv5vt4NY5OgpiM
- Other APL inspired language (mostly proprietary implementations): J,
K, Q
- J: Like APL but uses only ASCII
- K3: A version of K
- Q: built on top of K4 but proprietary
- Fun fact: APL inspired S, which in turn inspired R
- Scripts: