Train: Difference between revisions

Jump to navigation Jump to search
(Changed redirect target from Tacit#Trains to Tacit programming#Trains)
Tag: Redirect target changed
(Separate from tacit programming page)
Tag: Removed redirect
Line 1: Line 1:
#REDIRECT [[Tacit programming#Trains]]
A '''train''' is a compound function made up of a series of functions. It's written as an isolated expression (surrounded by parentheses or named) ending in a function. Defined by [[Ken Iverson]] and [[Eugene McDonnell]] in 1988 and added to [[Dyalog APL]] in 2014, trains are considered important for [[tacit programming]] and a characteristic of modern APL.
 
== Definition ==
 
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:
 
=== 3-trains ===
A 3-train is a ''fork'', so denoted because its structure resembles a three-tines fork, or a three-pronged pitchfork. The two outer functions are applied first, and their results are used as arguments to the middle function:
{|
|<source lang=apl>  (f g h) ⍵</source>|| {{←→}} ||<source lang=apl>(  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>
|}
 
=== 2-trains ===
Most dialects define a 2-train is an ''atop'', equivalent to the function derived using the [[Atop (operator)|Atop]] operator. The left function is applied [[monadic function|monadically]] on the result of the right function:
{|
|<source lang=apl>  (g h) ⍵</source>|| {{←→}} ||<source lang=apl>g (  h ⍵)</source>
|-
|<source lang=apl>⍺ (g h) ⍵</source>|| {{←→}} ||<source lang=apl>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]].
 
[[J]] instead defines the 2-train as a [[hook]], equivalent to the function derived using the [[Withe]] operator. The left function is always applied [[dyadic function|dyadically]], taking as right argument, the result of applying the right function on the right argument. If there is no left argument, the sole argument is used also as left argument:
{|
|<source lang=apl>  (g h) ⍵</source>|| {{←→}} ||<source lang=apl>⍵ g (h ⍵)</source>
|-
|<source lang=apl>⍺ (g h) ⍵</source>|| {{←→}} ||<source lang=apl>⍺ g (h ⍵)</source>
|}
 
== Problems caused by function-operator overloading ==
Trains that use a [[Function-operator_overloading|hybrid function-operator]] in its [[function]] role can run into the problems with the hybrid being parsed as a monadic [[operator]] instead of as a function. This happens when a function appears to the immediate left of the hybrid, causing this function to be bound as the hybrid's operand — the hybrid taking on an operator role — rather than supplying a left [[argument]] or post-processing the result.
 
For example, the attempted [[#3-trains|fork]] <source lang=apl inline>f/h</source> is actually parsed as the [[#2-trains|atop]] <source lang=apl inline>(f/)h</source> and the attempted atop <source lang=apl inline>f/</source> is actually parsed as a [[Windowed Reduce|Windowed Reduction]]. There are multiple [[Function-operator_overloading#Mitigation|ways to mitigate this issue]]. For example, the fork can be enforced using the [[Atop (operator)|Atop operator]] by applying identity to the hybrid's result as <source lang=apl inline>f⊢⍤/h</source> and the atop can be enforced by using the explicit Atop operator instead of a 2-train; <source lang=apl inline>f⍤/</source>.
 
No problem presents when left argument is supplied as an array (literal or by name reference) and when the hybrid is the leftmost token. For example, <source lang=apl inline>1 0 1/⌽</source> and <source lang=apl inline>/,⊃</source> are parsed as forks.
 
== References ==
<references />
 
{{APL syntax}}[[Category:Kinds of functions]][[Category:Defining functions]]
Retrieved from ‘https://aplwiki.com/wiki/Train