Simple examples: Difference between revisions
Jump to navigation
Jump to search
m (Text replacement - "<source" to "<syntaxhighlight") |
m (Text replacement - "</source>" to "</syntaxhighlight>") |
||
Line 6: | Line 6: | ||
<syntaxhighlight lang=apl> | <syntaxhighlight lang=apl> | ||
{(+⌿⍵)÷≢⍵} | {(+⌿⍵)÷≢⍵} | ||
</ | </syntaxhighlight> | ||
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. | 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>⍵</ | The <syntaxhighlight lang=apl inline>⍵</syntaxhighlight> refers to the argument of the function, a list (or 1-dimensional array) of numbers. The <syntaxhighlight lang=apl inline>≢</syntaxhighlight> denotes the [[tally]] function, which returns here the length of (number of elements in) the argument <syntaxhighlight lang=apl inline>⍵</syntaxhighlight>. The divide symbol <syntaxhighlight lang=apl inline>÷</syntaxhighlight> has its usual meaning. | ||
The parenthesised <syntaxhighlight lang=apl inline>+⌿⍵</ | The parenthesised <syntaxhighlight lang=apl inline>+⌿⍵</syntaxhighlight> denotes the sum of all the elements of <syntaxhighlight lang=apl inline>⍵</syntaxhighlight>. The <syntaxhighlight lang=apl inline>⌿</syntaxhighlight> operator combines with the <syntaxhighlight lang=apl inline>+</syntaxhighlight> function: the <syntaxhighlight lang=apl inline>⌿</syntaxhighlight> fixes the <syntaxhighlight lang=apl inline>+</syntaxhighlight> function between each element of <syntaxhighlight lang=apl inline>⍵</syntaxhighlight>, so that | ||
<syntaxhighlight lang=apl> | <syntaxhighlight lang=apl> | ||
+⌿ 1 2 3 4 5 6 | +⌿ 1 2 3 4 5 6 | ||
21 | 21 | ||
</ | </syntaxhighlight> | ||
is the same as | is the same as | ||
<syntaxhighlight lang=apl> | <syntaxhighlight lang=apl> | ||
1+2+3+4+5+6 | 1+2+3+4+5+6 | ||
21 | 21 | ||
</ | </syntaxhighlight> | ||
=== Operators === | === Operators === | ||
[[Operator]]s like <syntaxhighlight lang=apl inline>⌿</ | [[Operator]]s like <syntaxhighlight lang=apl inline>⌿</syntaxhighlight> can be used to derive new functions not only from [[primitive function]]s like <syntaxhighlight lang=apl inline>+</syntaxhighlight>, but also from defined functions. For example | ||
<syntaxhighlight lang=apl> | <syntaxhighlight lang=apl> | ||
{⍺,', ',⍵}⌿ | {⍺,', ',⍵}⌿ | ||
</ | </syntaxhighlight> | ||
will transform a list of strings representing words into a comma-separated list: | will transform a list of strings representing words into a comma-separated list: | ||
<syntaxhighlight lang=apl> | <syntaxhighlight lang=apl> | ||
Line 32: | Line 32: | ||
│cow, sheep, cat, dog│ | │cow, sheep, cat, dog│ | ||
└────────────────────┘ | └────────────────────┘ | ||
</ | </syntaxhighlight> | ||
So back to our mean example. <syntaxhighlight lang=apl inline>(+⌿⍵)</ | So back to our mean example. <syntaxhighlight lang=apl inline>(+⌿⍵)</syntaxhighlight> gives the sum of the list, which is then divided by <syntaxhighlight lang=apl inline>≢⍵</syntaxhighlight>, the number elements in it. | ||
<syntaxhighlight lang=apl> | <syntaxhighlight lang=apl> | ||
{(+⌿⍵)÷≢⍵} 3 4.5 7 21 | {(+⌿⍵)÷≢⍵} 3 4.5 7 21 | ||
8.875 | 8.875 | ||
</ | </syntaxhighlight> | ||
=== Tacit programming === | === Tacit programming === | ||
Line 47: | Line 47: | ||
(+⌿÷≢) 3 4.5 7 21 | (+⌿÷≢) 3 4.5 7 21 | ||
8.875 | 8.875 | ||
</ | </syntaxhighlight> | ||
This is a so called 3-train, also known as a ''fork''. It is evaluated like this: | 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</ | |<syntaxhighlight lang=apl>(+⌿ ÷ ≢) 3 4.5 7 21</syntaxhighlight>|| {{←→}} ||<syntaxhighlight lang=apl>(+⌿ 3 4.5 7 21) ÷ (≢ 3 4.5 7 21)</syntaxhighlight> | ||
|} | |} | ||
Note that <syntaxhighlight lang=apl inline>+⌿</ | Note that <syntaxhighlight lang=apl inline>+⌿</syntaxhighlight> is evaluated as a single derived function. | ||
The general scheme for monadic 3-trains is the following: | The general scheme for monadic 3-trains is the following: | ||
{| | {| | ||
|<syntaxhighlight lang=apl>(f g h) ⍵</ | |<syntaxhighlight lang=apl>(f g h) ⍵</syntaxhighlight>|| {{←→}} ||<syntaxhighlight lang=apl>(f ⍵) g (h ⍵)</syntaxhighlight> | ||
|} | |} | ||
Line 65: | Line 65: | ||
APL represents text as character lists (vectors), making many text operations trivial. | APL represents text as character lists (vectors), making many text operations trivial. | ||
=== Split text by delimiter === | === Split text by delimiter === | ||
<syntaxhighlight lang=apl inline>≠</ | <syntaxhighlight lang=apl inline>≠</syntaxhighlight> gives 1 for true and 0 for false. It [[scalar function|pairs up]] a single element argument with all the elements of the other arguments: | ||
<syntaxhighlight lang=apl> | <syntaxhighlight lang=apl> | ||
','≠'comma,delimited,text' | ','≠'comma,delimited,text' | ||
1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 1 1 1 1 | 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 1 1 1 1 | ||
</ | </syntaxhighlight> | ||
<syntaxhighlight lang=apl inline>⊢</ | <syntaxhighlight lang=apl inline>⊢</syntaxhighlight> returns its right argument: | ||
<syntaxhighlight lang=apl> | <syntaxhighlight lang=apl> | ||
','⊢'comma,delimited,text' | ','⊢'comma,delimited,text' | ||
comma,delimited,text | comma,delimited,text | ||
</ | </syntaxhighlight> | ||
<syntaxhighlight lang=apl inline>⊆</ | <syntaxhighlight lang=apl inline>⊆</syntaxhighlight> returns a list of runs as indicated by runs of 1s, leaving out elements indicated by 0s: | ||
<syntaxhighlight lang=apl> | <syntaxhighlight lang=apl> | ||
1 1 0 1 1 1⊆'Hello!' | 1 1 0 1 1 1⊆'Hello!' | ||
Line 81: | Line 81: | ||
│He│lo!│ | │He│lo!│ | ||
└──┴───┘ | └──┴───┘ | ||
</ | </syntaxhighlight> | ||
We use the comparison [[vector]] to [[partition]] the right argument: | We use the comparison [[vector]] to [[partition]] the right argument: | ||
Line 90: | Line 90: | ||
│comma│delimited│text│ | │comma│delimited│text│ | ||
└─────┴─────────┴────┘ | └─────┴─────────┴────┘ | ||
</ | </syntaxhighlight> | ||
{{Works in|[[Dyalog APL]]}} | {{Works in|[[Dyalog APL]]}} | ||
Notice that you can read the [[tacit]] function <syntaxhighlight lang=apl inline>≠⊆⊢</ | Notice that you can read the [[tacit]] function <syntaxhighlight lang=apl inline>≠⊆⊢</syntaxhighlight> 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>⊂</ | Many dialects do not support the above [[tacit]] syntax, and use the [[glyph]] <syntaxhighlight lang=apl inline>⊂</syntaxhighlight> for partition [[primitive function]]. In such dialects, the following formulation can be used: | ||
<syntaxhighlight lang=apl> | <syntaxhighlight lang=apl> | ||
(','≠s)⊂s←'comma,delimited,text' | (','≠s)⊂s←'comma,delimited,text' | ||
</ | </syntaxhighlight> | ||
{{Works in|[[APL2]], [[APLX]], [[GNU APL]]}} | {{Works in|[[APL2]], [[APLX]], [[GNU APL]]}} | ||
This assigns the text to the variable <syntaxhighlight lang=apl inline>s</ | This assigns the text to the variable <syntaxhighlight lang=apl inline>s</syntaxhighlight>, then separately computes the partitioning vector and applies it. | ||
=== Indices of multiple elements === | === Indices of multiple elements === | ||
<syntaxhighlight lang=apl inline>∊</ | <syntaxhighlight lang=apl inline>∊</syntaxhighlight> gives us a mask for elements (characters) in the left argument that are members of the right argument: | ||
<syntaxhighlight lang=apl> | <syntaxhighlight lang=apl> | ||
'mississippi'∊'sp' | 'mississippi'∊'sp' | ||
0 0 1 1 0 1 1 0 1 1 0 | 0 0 1 1 0 1 1 0 1 1 0 | ||
</ | </syntaxhighlight> | ||
<syntaxhighlight lang=apl inline>⍸</ | <syntaxhighlight lang=apl inline>⍸</syntaxhighlight> gives us the indices where true (1): | ||
<syntaxhighlight lang=apl> | <syntaxhighlight lang=apl> | ||
⍸'mississippi'∊'sp' | ⍸'mississippi'∊'sp' | ||
3 4 6 7 9 10 | 3 4 6 7 9 10 | ||
</ | </syntaxhighlight> | ||
We can combine this into an anonymous infix (dyadic) function: | We can combine this into an anonymous infix (dyadic) function: | ||
<syntaxhighlight lang=apl> | <syntaxhighlight lang=apl> | ||
'mississippi' (⍸∊) 'sp' | 'mississippi' (⍸∊) 'sp' | ||
3 4 6 7 9 10 | 3 4 6 7 9 10 | ||
</ | </syntaxhighlight> | ||
{{Works in|[[Dyalog APL]], [[NARS2000]], [[dzaima/APL]]}} | {{Works in|[[Dyalog APL]], [[NARS2000]], [[dzaima/APL]]}} | ||
Line 127: | Line 127: | ||
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 0 | ||
</ | </syntaxhighlight> | ||
Then it is simply a matter of performing a sum-reduce <syntaxhighlight lang=apl inline>+/</ | Then it is simply a matter of performing a sum-reduce <syntaxhighlight lang=apl inline>+/</syntaxhighlight> to calculate the total frequency of each character:<ref name="Marshall LambaConf 2019">[[Marshall Lochbaum]] used this example as part of his talk on [[Outer Product]] at LambdaConf 2019.</ref> | ||
<syntaxhighlight lang=apl> | <syntaxhighlight lang=apl> | ||
+/ 'abcd' ∘.= 'cabbage' | +/ 'abcd' ∘.= 'cabbage' | ||
2 2 1 0 | 2 2 1 0 | ||
</ | </syntaxhighlight> | ||
=== Parenthesis nesting level === | === Parenthesis nesting level === | ||
Line 138: | Line 138: | ||
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. | 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 ==== | ==== Method A ==== | ||
For this more complex computation, we can expand on the previous example's use of <syntaxhighlight lang=apl inline>∘.=</ | For this more complex computation, we can expand on the previous example's use of <syntaxhighlight lang=apl inline>∘.=</syntaxhighlight>. First we compare all characters to the opening and closing characters; | ||
<syntaxhighlight lang=apl> | <syntaxhighlight lang=apl> | ||
'()'∘.='plus(square(a),plus(square(b),times(2,plus(a,b)))' | '()'∘.='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 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 | 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 | ||
</ | </syntaxhighlight> | ||
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: | 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> | <syntaxhighlight lang=apl> | ||
-⌿'()'∘.='plus(square(a),plus(square(b),times(2,plus(a,b)))' | -⌿'()'∘.='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 | 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 | ||
</ | </syntaxhighlight> | ||
The running sum is what we're looking for: | The running sum is what we're looking for: | ||
<syntaxhighlight lang=apl> | <syntaxhighlight lang=apl> | ||
+\-⌿'()'∘.='plus(square(a),plus(square(b),times(2,plus(a,b)))' | +\-⌿'()'∘.='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 | 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 | ||
</ | </syntaxhighlight> | ||
{{Works in|all APLs}} | {{Works in|all APLs}} | ||
==== Method B ==== | ==== Method B ==== | ||
Alternatively, we can utilise that if the [[Index Of]] function <syntaxhighlight lang=apl inline>⍳</ | Alternatively, we can utilise that if the [[Index Of]] function <syntaxhighlight lang=apl inline>⍳</syntaxhighlight> 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> | <syntaxhighlight lang=apl> | ||
'ABBA'⍳'ABC' | 'ABBA'⍳'ABC' | ||
Line 162: | Line 162: | ||
'()'⍳'plus(square(a),plus(square(b),times(2,plus(a,b)))' | '()'⍳'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 | 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 | ||
</ | </syntaxhighlight> | ||
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: | 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> | <syntaxhighlight lang=apl> | ||
1 ¯1 0['()'⍳'plus(square(a),plus(square(b),times(2,plus(a,b)))'] | 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 | 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 | ||
</ | </syntaxhighlight> | ||
The running sum is what we're looking for: | The running sum is what we're looking for: | ||
<syntaxhighlight lang=apl> | <syntaxhighlight lang=apl> | ||
+\1 ¯1 0['()'⍳'plus(square(a),plus(square(b),times(2,plus(a,b)))'] | +\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 | 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 | ||
</ | </syntaxhighlight> | ||
{{Works in|all APLs}} | {{Works in|all APLs}} | ||
Line 189: | Line 189: | ||
│MPLFF│⌺ ⌺⌺│ | │MPLFF│⌺ ⌺⌺│ | ||
└─────┴─────┘ | └─────┴─────┘ | ||
</ | </syntaxhighlight> | ||
</p> | </p> | ||
Retrieve elements of the grid where there are spaces in the grille. | Retrieve elements of the grid where there are spaces in the grille. | ||
Line 195: | Line 195: | ||
grid[⍸grille=' '] | grid[⍸grille=' '] | ||
ILIKEAPL | ILIKEAPL | ||
</ | </syntaxhighlight> | ||
An alternative method using [[ravel]]. | An alternative method using [[ravel]]. | ||
<syntaxhighlight lang=apl> | <syntaxhighlight lang=apl> | ||
(' '=,grille)/,grid | (' '=,grille)/,grid | ||
ILIKEAPL | ILIKEAPL | ||
</ | </syntaxhighlight> | ||
===References=== | ===References=== | ||
<references/> | <references/> |