Tacit programming: Difference between revisions
(→Trains) |
|||
Line 32: | Line 32: | ||
== Trains == | == Trains == | ||
A train is a series of functions in isolation. An isolated function is either surrounded by parentheses or named. | A train is a series of functions in isolation. An isolated function is either surrounded by parentheses or named. Below, <source lang=apl inline>⍺</source> and <source lang=apl inline>⍵</source> refer to the arguments of the train. <source lang=apl inline>f</source>, <source lang=apl inline>g</source>, and <source lang=apl inline>h</source> are function (which themselves can be tacit or not), and <source lang=apl inline>A</source> is an array. The arguments are processed by the following rules: | ||
A 2-train is an ''atop'': | A 2-train is an ''atop'': | ||
<source lang=apl> | {| | ||
|<source lang=apl> (g h) ⍵</source>|| {{←→}} ||<source lang=apl>g ( h ⍵)</source> | |||
⍺ (g h) ⍵ | |- | ||
</source> | |<source lang=apl>⍺ (g h) ⍵</source>|| {{←→}} ||<source lang=apl>g (⍺ h ⍵)</source> | ||
|} | |||
A 3-train is a ''fork'': | A 3-train is a ''fork'': | ||
<source lang=apl> | {| | ||
|<source lang=apl> (f g h) ⍵</source>|| {{←→}} ||<source lang=apl>( f ⍵) g ( h ⍵)</source> | |||
⍺ (f g h) ⍵ | |- | ||
</source> | |<source lang=apl>⍺ (f g h) ⍵</source>|| {{←→}} ||<source lang=apl>(⍺ f ⍵) g (⍺ h ⍵)</source> | ||
|} | |||
The ''left tine'' of a fork can be an array: | |||
{| | |||
|<source lang=apl> (A g h)</source>|| {{←→}} ||<source lang=apl>A g ( h ⍵)</source> | |||
|- | |||
|<source lang=apl>⍺ (A g h) ⍵</source>|| {{←→}} ||<source lang=apl>A g (⍺ h ⍵)</source> | |||
|} | |||
Only [[dzaima/APL]] allows <source lang=apl inline>(A h)</source>, which it treats as <source lang=apl inline>A∘h</source>.<ref>dzaima/APL: [https://github.com/dzaima/APL/blob/ceea05e25687988ed0980a4abf4b9249b736543f/docs/differences.txt#L19 Differences from Dyalog APL]. Retrieved 09 Jan 2020.</ref> | Only [[dzaima/APL]] allows <source lang=apl inline>(A h)</source>, which it treats as <source lang=apl inline>A∘h</source>.<ref>dzaima/APL: [https://github.com/dzaima/APL/blob/ceea05e25687988ed0980a4abf4b9249b736543f/docs/differences.txt#L19 Differences from Dyalog APL]. Retrieved 09 Jan 2020.</ref> | ||
Revision as of 15:40, 9 January 2020
Tacit functions apply to implicit arguments following a small set of rules. This is in contrast to the explicit use of arguments in dfns (⍺ ⍵
) and tradfns (which have named arguments). Known dialects which implement trains are Dyalog APL, dzaima/APL, ngn/apl and NARS2000.
Primitives
All primitive functions are tacit. Some APLs allow primitive functions to be named.
plus ← + times ← × 6 times 3 plus 5 48
Derived functions
Functions derived from a monadic operator and an operand, or from a dyadic operator and two operands are tacit functions:
Sum ← +/ Sum ⍳10 55 Dot ← +.× 3 1 4 dot 2 7 1 17
Derived operators
A dyadic operator with its right operand forms a tacit monadic operator:
1(+⍣2)10 12 Twice ← ⍣2 1 +Twice 10 12
Trains
A train is a series of functions in isolation. An isolated function is either surrounded by parentheses or named. Below, ⍺
and ⍵
refer to the arguments of the train. f
, g
, and h
are function (which themselves can be tacit or not), and A
is an array. The arguments are processed by the following rules:
A 2-train is an atop:
(g h) ⍵ |
g ( h ⍵) | |
⍺ (g h) ⍵ |
g (⍺ h ⍵) |
A 3-train is a fork:
(f g h) ⍵ |
( f ⍵) g ( h ⍵) | |
⍺ (f g h) ⍵ |
(⍺ f ⍵) g (⍺ h ⍵) |
The left tine of a fork can be an array:
(A g h) |
A g ( h ⍵) | |
⍺ (A g h) ⍵ |
A g (⍺ h ⍵) |
Only dzaima/APL allows (A h)
, which it treats as A∘h
.[1]
Examples
One of the major benefits of tacit programming is the ability to convey a short, well-defined idea as an isolated expression. This aids both human readability (semantic density) and the computer's ability to interpret code, potentially executing special code for particular idioms.
Plus and minus
(+,-) 2 ⍝ ±2 2 ¯2 5 (+,-) 2 ⍝ 5±2 7 3
Arithmetic mean
(+⌿÷≢) ⍳10 ⍝ Mean of the first ten integers 5.5 (+⌿÷≢) 5 4⍴⍳4 ⍝ Mean of columns in a matrix 1 2 3 4
Fractions
We can convert decimal numbers to fractions. For example, we can convert to the improper fraction with
(1∧⊢,÷)2.625 21 8
Alternatively, we can convert it to the mixed fraction with A mixed fraction:
(1∧0 1∘⊤,÷)2.625 2 5 8
Is it a palindrome?
(⌽≡⊢)'racecar' 1 (⌽≡⊢)'racecat' 0
Split delimited text
','(≠⊆⊢)'comma,delimited,text' ┌─────┬─────────┬────┐ │comma│delimited│text│ └─────┴─────────┴────┘ ' '(≠⊆⊢)'space delimited text' ┌─────┬─────────┬────┐ │space│delimited│text│ └─────┴─────────┴────┘
Component of a vector in the direction of another vector
Sometimes a train can make an expression nicely resemble its equivalent definition in traditional mathematical notation. As an example, here is a program to compute the component of a vector in the direction of another vector :
Root ← *∘÷⍨ ⍝ Nth root Norm ← 2 Root +.×⍨ ⍝ Magnitude (norm) of numeric vector in Euclidean space Unit ← ⊢÷Norm ⍝ Unit vector in direction of vector ⍵ InDirOf ← (⊢×+.×)∘Unit ⍝ Component of vector ⍺ in direction of vector ⍵ 3 5 2 InDirOf 0 0 1 ⍝ Trivial example 0 0 2
For a more parallel comparison of the notations, see the comparison with traditional mathematics.
External links
Tutorials
- Transcribing to and reading trains
- How to read trains in Dyalog APL code (video)
- Function trains in APL (video)
Documentation =
References
- ↑ dzaima/APL: Differences from Dyalog APL. Retrieved 09 Jan 2020.