Simple examples
This page contains examples that show APL's strengths. The examples require minimal background and have no special dependencies. If these examples are too simple for you, have a look at our advanced examples.
Arithmetic mean
Here is an APL program to calculate the average (arithmetic mean) of a list of numbers, written as a dfn: <syntaxhighlight lang=apl>
{(+⌿⍵)÷≢⍵}
</source> It is unnamed: the enclosing braces mark it as a function definition. It can be assigned a name for use later, or used anonymously in a more complex expression.
The <syntaxhighlight lang=apl inline>⍵</source> refers to the argument of the function, a list (or 1-dimensional array) of numbers. The <syntaxhighlight lang=apl inline>≢</source> denotes the tally function, which returns here the length of (number of elements in) the argument <syntaxhighlight lang=apl inline>⍵</source>. The divide symbol <syntaxhighlight lang=apl inline>÷</source> has its usual meaning.
The parenthesised <syntaxhighlight lang=apl inline>+⌿⍵</source> denotes the sum of all the elements of <syntaxhighlight lang=apl inline>⍵</source>. The <syntaxhighlight lang=apl inline>⌿</source> operator combines with the <syntaxhighlight lang=apl inline>+</source> function: the <syntaxhighlight lang=apl inline>⌿</source> fixes the <syntaxhighlight lang=apl inline>+</source> function between each element of <syntaxhighlight lang=apl inline>⍵</source>, so that <syntaxhighlight lang=apl>
+⌿ 1 2 3 4 5 6
21 </source> is the same as <syntaxhighlight lang=apl>
1+2+3+4+5+6
21 </source>
Operators
Operators like <syntaxhighlight lang=apl inline>⌿</source> can be used to derive new functions not only from primitive functions like <syntaxhighlight lang=apl inline>+</source>, but also from defined functions. For example <syntaxhighlight lang=apl>
{⍺,', ',⍵}⌿
</source> will transform a list of strings representing words into a comma-separated list: <syntaxhighlight lang=apl>
{⍺,', ',⍵}⌿'cow' 'sheep' 'cat' 'dog'
┌────────────────────┐ │cow, sheep, cat, dog│ └────────────────────┘ </source> So back to our mean example. <syntaxhighlight lang=apl inline>(+⌿⍵)</source> gives the sum of the list, which is then divided by <syntaxhighlight lang=apl inline>≢⍵</source>, the number elements in it. <syntaxhighlight lang=apl>
{(+⌿⍵)÷≢⍵} 3 4.5 7 21
8.875 </source>
Tacit programming
- Main article: Tacit programming
In APL’s tacit definition, no braces are needed to mark the definition of a function: primitive functions just combine in a way that enables us to omit any reference to the function arguments — hence tacit. Here is the same calculation written tacitly: <syntaxhighlight lang=apl>
(+⌿÷≢) 3 4.5 7 21
8.875 </source>
This is a so called 3-train, also known as a fork. It is evaluated like this:
<syntaxhighlight lang=apl>(+⌿ ÷ ≢) 3 4.5 7 21</source> | <syntaxhighlight lang=apl>(+⌿ 3 4.5 7 21) ÷ (≢ 3 4.5 7 21)</source> |
Note that <syntaxhighlight lang=apl inline>+⌿</source> is evaluated as a single derived function. The general scheme for monadic 3-trains is the following:
<syntaxhighlight lang=apl>(f g h) ⍵</source> | <syntaxhighlight lang=apl>(f ⍵) g (h ⍵)</source> |
But other types of trains are also possible.
Text processing
APL represents text as character lists (vectors), making many text operations trivial.
Split text by delimiter
<syntaxhighlight lang=apl inline>≠</source> gives 1 for true and 0 for false. It pairs up a single element argument with all the elements of the other arguments: <syntaxhighlight lang=apl>
','≠'comma,delimited,text'
1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 1 1 1 1 </source> <syntaxhighlight lang=apl inline>⊢</source> returns its right argument: <syntaxhighlight lang=apl>
','⊢'comma,delimited,text'
comma,delimited,text </source> <syntaxhighlight lang=apl inline>⊆</source> returns a list of runs as indicated by runs of 1s, leaving out elements indicated by 0s: <syntaxhighlight lang=apl>
1 1 0 1 1 1⊆'Hello!'
┌──┬───┐ │He│lo!│ └──┴───┘ </source> We use the comparison vector to partition the right argument:
Try it now! <syntaxhighlight lang=apl>
','(≠⊆⊢)'comma,delimited,text'
┌─────┬─────────┬────┐ │comma│delimited│text│ └─────┴─────────┴────┘ </source>
Notice that you can read the tacit function <syntaxhighlight lang=apl inline>≠⊆⊢</source> like an English sentence: The inequality partitions the right argument.
Many dialects do not support the above tacit syntax, and use the glyph <syntaxhighlight lang=apl inline>⊂</source> for partition primitive function. In such dialects, the following formulation can be used: <syntaxhighlight lang=apl>
(','≠s)⊂s←'comma,delimited,text'
</source>
This assigns the text to the variable <syntaxhighlight lang=apl inline>s</source>, then separately computes the partitioning vector and applies it.
Indices of multiple elements
<syntaxhighlight lang=apl inline>∊</source> gives us a mask for elements (characters) in the left argument that are members of the right argument: <syntaxhighlight lang=apl>
'mississippi'∊'sp'
0 0 1 1 0 1 1 0 1 1 0 </source> <syntaxhighlight lang=apl inline>⍸</source> gives us the indices where true (1): <syntaxhighlight lang=apl>
⍸'mississippi'∊'sp'
3 4 6 7 9 10 </source> We can combine this into an anonymous infix (dyadic) function: <syntaxhighlight lang=apl>
'mississippi' (⍸∊) 'sp'
3 4 6 7 9 10 </source>
Frequency of characters in a string
The Outer Product allows for an intuitive way to compute the occurrence of characters at a given location in a string: <syntaxhighlight lang=apl>
'abcd' ∘.= 'cabbage' 0 1 0 0 1 0 0 0 0 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
</source> Then it is simply a matter of performing a sum-reduce <syntaxhighlight lang=apl inline>+/</source> to calculate the total frequency of each character:[1] <syntaxhighlight lang=apl>
+/ 'abcd' ∘.= 'cabbage' 2 2 1 0
</source>
Parenthesis nesting level
"Ken was showing some slides — and one of his slides had something on it that I was later to learn was an APL one-liner. And he tossed this off as an example of the expressiveness of the APL notation. I believe the one-liner was one of the standard ones for indicating the nesting level of the parentheses in an algebraic expression. But the one-liner was very short — ten characters, something like that — and having been involved with programming things like that for a long time and realizing that it took a reasonable amount of code to do, I looked at it and said, “My God, there must be something in this language.”"
Alan Perlis. Almost Perfect Artifacts Improve only in Small Ways: APL is more French than English at APL78.
What was the one-liner for the nesting level of parentheses? It would take a bit of work to figure out, because at the time of the meeting Perlis described, no APL implementation existed. Two possibilities are explained here.
Method A
For this more complex computation, we can expand on the previous example's use of <syntaxhighlight lang=apl inline>∘.=</source>. First we compare all characters to the opening and closing characters; <syntaxhighlight lang=apl>
'()'∘.='plus(square(a),plus(square(b),times(2,plus(a,b)))'
0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 </source> An opening increases the current level, while a closing decreases, so we convert this to changes (or deltas) by subtracting the bottom row from the top row: <syntaxhighlight lang=apl>
-⌿'()'∘.='plus(square(a),plus(square(b),times(2,plus(a,b)))'
0 0 0 0 1 0 0 0 0 0 0 1 0 ¯1 0 0 0 0 0 1 0 0 0 0 0 0 1 0 ¯1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 ¯1 ¯1 ¯1 </source> The running sum is what we're looking for: <syntaxhighlight lang=apl>
+\-⌿'()'∘.='plus(square(a),plus(square(b),times(2,plus(a,b)))'
0 0 0 0 1 1 1 1 1 1 1 2 2 1 1 1 1 1 1 2 2 2 2 2 2 2 3 3 2 2 2 2 2 2 2 3 3 3 3 3 3 3 4 4 4 4 3 2 1 </source>
Method B
Alternatively, we can utilise that if the Index Of function <syntaxhighlight lang=apl inline>⍳</source> doesn't find what it is looking for, it returns the next index after the last element in the the lookup array: <syntaxhighlight lang=apl>
'ABBA'⍳'ABC'
1 2 5
'()'⍳'plus(square(a),plus(square(b),times(2,plus(a,b)))'
3 3 3 3 1 3 3 3 3 3 3 1 3 2 3 3 3 3 3 1 3 3 3 3 3 3 1 3 2 3 3 3 3 3 3 1 3 3 3 3 3 3 1 3 3 3 2 2 2 </source> Whenever we have a 1 the parenthesis level increases, and when we have a 2 it decreases. If we have a 3, it remains as-is. We can do this mapping by indexing into these values: <syntaxhighlight lang=apl>
1 ¯1 0['()'⍳'plus(square(a),plus(square(b),times(2,plus(a,b)))']
0 0 0 0 1 0 0 0 0 0 0 1 0 ¯1 0 0 0 0 0 1 0 0 0 0 0 0 1 0 ¯1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 ¯1 ¯1 ¯1 </source> The running sum is what we're looking for: <syntaxhighlight lang=apl>
+\1 ¯1 0['()'⍳'plus(square(a),plus(square(b),times(2,plus(a,b)))']
0 0 0 0 1 1 1 1 1 1 1 2 2 1 1 1 1 1 1 2 2 2 2 2 2 2 3 3 2 2 2 2 2 2 2 3 3 3 3 3 3 3 4 4 4 4 3 2 1 </source>
Grille cypher
A grille is a 500 year old method for encrypting messages.
Represent both the grid of letters and the grille as character matrices. <syntaxhighlight lang=apl> ⎕←(grid grille)←5 5∘⍴¨'VRYIALCLQIFKNEVPLARKMPLFF' '⌺⌺⌺ ⌺ ⌺⌺⌺ ⌺ ⌺ ⌺⌺⌺ ⌺⌺⌺ ⌺⌺' ┌─────┬─────┐ │VRYIA│⌺⌺⌺ ⌺│ │LCLQI│ ⌺⌺⌺ │ │FKNEV│⌺ ⌺ ⌺│ │PLARK│⌺⌺ ⌺⌺│ │MPLFF│⌺ ⌺⌺│ └─────┴─────┘ </source>
Retrieve elements of the grid where there are spaces in the grille. <syntaxhighlight lang=apl>
grid[⍸grille=' ']
ILIKEAPL </source> An alternative method using ravel. <syntaxhighlight lang=apl>
(' '=,grille)/,grid
ILIKEAPL </source>
References
- ↑ Marshall Lochbaum used this example as part of his talk on Outer Product at LambdaConf 2019.
APL development [edit] | |
---|---|
Interface | Session ∙ Typing glyphs (on Linux) ∙ Fonts ∙ Text editors |
Publications | Introductions ∙ Learning resources ∙ Simple examples ∙ Advanced examples ∙ Mnemonics ∙ ISO 8485:1989 ∙ ISO/IEC 13751:2001 ∙ A Dictionary of APL ∙ Case studies ∙ Documentation suites ∙ Books ∙ Papers ∙ Videos ∙ APL Quote Quad ∙ Vector journal ∙ Terminology (Chinese, German) ∙ Neural networks ∙ Error trapping with Dyalog APL (in forms) |
Sharing code | Backwards compatibility ∙ APLcart ∙ APLTree ∙ APL-Cation ∙ Dfns workspace ∙ Tatin ∙ Cider |
Implementation | Resources ∙ Open-source ∙ Magic function ∙ Performance ∙ APL hardware |
Developers | Timeline of corporations ∙ APL2000 ∙ Dyalog ∙ IBM ∙ IPSA ∙ STSC |