4,500
edits
(→Trains) |
No edit summary |
||
(27 intermediate revisions by 5 users not shown) | |||
Line 1: | Line 1: | ||
Tacit functions apply to implicit arguments | Tacit functions apply to implicit arguments. This is in contrast to the explicit use of arguments in [[dfns]] (<source inline lang=apl>⍺ ⍵</source>) and [[tradfns]] (which have named arguments). Some APL dialects allow to combine functions into '''trains''' following a small set of rules. This allows creating complex derived functions without specifying any arguments explicitly. | ||
Known dialects which implement trains are [[Dyalog APL]], [[dzaima/APL]], [[ngn/apl]] and [[NARS2000]]. | |||
== Primitives == | == Primitives == | ||
Line 32: | Line 34: | ||
== 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 functions (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> See [[Bind]]. | |||
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> | |||
== Examples == | == 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 [[ | 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 [[idiom]]s. | ||
=== Plus and minus === | === Plus and minus === | ||
<source lang=apl> | <source lang=apl> | ||
(+,-)2 | (+,-) 2 ⍝ ±2 | ||
2 ¯2 | 2 ¯2 | ||
5 (+,-) 2 ⍝ 5±2 | |||
7 3 | |||
</source> | </source> | ||
Line 76: | Line 77: | ||
=== Fractions === | === Fractions === | ||
We can convert decimal numbers to fractions. For example, we can convert <math>2.625</math> to the improper fraction <math>21 | We can convert decimal numbers to fractions. For example, we can convert <math>2.625</math> to the improper fraction <math>\tfrac{21}{8}</math> with | ||
<source lang=apl> | <source lang=apl> | ||
(1∧⊢,÷)2.625 | (1∧⊢,÷)2.625 | ||
21 8 | 21 8 | ||
</source> | </source> | ||
Alternatively, we can convert it to the mixed fraction <math>2{5 | Alternatively, we can convert it to the mixed fraction <math>2\tfrac{5}{8}</math> with a mixed fraction: | ||
<source lang=apl> | <source lang=apl> | ||
(1∧0 1∘⊤,÷)2.625 | (1∧0 1∘⊤,÷)2.625 | ||
Line 119: | Line 119: | ||
0 0 2 | 0 0 2 | ||
</source> | </source> | ||
For a more parallel comparison of the notations, see the [[Comparison_with_traditional_mathematics#Practical_example|comparison with traditional mathematics]]. | For a more parallel comparison of the notations, see the [[Comparison_with_traditional_mathematics#Practical_example|comparison with traditional mathematics]]. | ||
{{APL syntax}} | |||
===The Number of the Beast=== | |||
The following expression for computing the [[wikipedia:666 (number)|number of the Beast]] (and of [[I.P. Sharp]]'s APL-based email system, [[666 BOX]]) nicely illustrates how to read a train. | |||
<source lang=apl> | |||
((+.×⍨⊢~∘.×⍨)1↓⍳)17 ⍝ Accursed train | |||
666 | |||
</source> | |||
First, <source lang=apl inline>((+.×⍨⊢~∘.×)1↓⍳)</source> is supplied with only one argument <source lang=apl inline>17</source> and is thus interpreted monadically. | |||
Second, <source lang=apl inline>(+.×⍨⊢~∘.×⍨)1↓⍳</source> is a 4-train: reading right-to-left, the last 3 components are interpreted as the fork <source lang=apl inline>1↓⍳</source> and the 4-train is interpreted as the atop <source lang=apl inline>(+.×⍨⊢~∘.×⍨)(1↓⍳)</source>. | |||
Similarly, <source lang=apl inline>(+.×⍨⊢~∘.×⍨)</source> is also a 4-train and interpreted as the atop <source lang=apl inline>+.×⍨(⊢~∘.×⍨)</source>. | |||
Thus the accursed train is interpreted as <source lang=apl inline>((+.×⍨(⊢~∘.×⍨))(1↓⍳))17</source>. Having read the train, we now evaluate it monadically. | |||
<source lang=apl> | |||
((+.×⍨(⊢~∘.×⍨))(1↓⍳))17 ⍝ Accursed train as an atop over a fork atop a fork | |||
+.×⍨(⊢~∘.×⍨)1↓⍳17 ⍝ Atop evalution | |||
+.×⍨(⊢1↓⍳17)~∘.×⍨1↓⍳17 ⍝ Fork evalution | |||
+.×⍨(1↓⍳17)~∘.×⍨1↓⍳17 ⍝ ⊢ evaluation | |||
+.×⍨2 3 5 7 11 13 15 17 ⍝ numbers 2 through 17 without those appearing in their multiplication table are primes | |||
666 ⍝ the sum of the squares of the primes up to 17 | |||
</source> | |||
Note that <source lang=apl inline>((⊢⍨∘.×⍨)1↓⍳)</source> is a train computing primes up to the given input. | |||
A more satisfying variation of the accursed train is the following. | |||
<source lang=apl> | |||
(⍎⊢,⍕∘≢)'((+.×⍨⊢~∘.×⍨)1↓⍳)' ⍝ Accursed train 2.0 | |||
⍎(⊢,⍕∘≢)'((+.×⍨⊢~∘.×⍨)1↓⍳)' ⍝ 4-train intepreted as an atop | |||
⍎(⊢'((+.×⍨⊢~∘.×⍨)1↓⍳)'),⍕∘≢'((+.×⍨⊢~∘.×⍨)1↓⍳)' ⍝ fork evaluation | |||
⍎'((+.×⍨⊢~∘.×⍨)1↓⍳)','17' ⍝ ⊢ evaluation and ⍕∘≢ evaluation | |||
⍎'((+.×⍨⊢~∘.×⍨)1↓⍳)17' ⍝ , evaluation | |||
666 ⍝ ⍎ executes original Accursed train | |||
</source> | |||
== External links == | |||
=== Tutorials === | |||
* Dyalog: [http://help.dyalog.com/16.0/Content/RelNotes14.0/Function%20Trains.htm version 14.0 release notes] | |||
* [[APL Cultivation]]: [https://chat.stackexchange.com/rooms/52405/conversation/lesson-23-transcribing-to-and-reading-trains Transcribing to and reading trains] | |||
* [[APLtrainer]]: [https://www.youtube.com/watch?v=kt4lMZbn-so How to read trains in Dyalog APL code] (video) | |||
* [[APLtrainer]]: [https://www.youtube.com/watch?v=A2LqqBosvY0 Function trains in APL] (video) | |||
* [[Dyalog webinar]]: [https://www.youtube.com/watch?v=Enlh5qwwDuY?t=440 Train Spotting in Dyalog APL] (video) | |||
* [[Dyalog '13]]: [https://www.youtube.com/watch?v=7-93GzDqC08 Train Spotting in Version 14.0] (video) | |||
=== Documentation === | |||
* [http://help.dyalog.com/16.0/Content/RelNotes14.0/Function%20Trains.htm Announcement] | |||
* [http://help.dyalog.com/latest/Content/Language/Introduction/Trains.htm Dyalog] | |||
== References == | |||
<references/> | |||
{{APL syntax}}[[Category:Tacit programming| ]] |