Split composition: Difference between revisions

From APL Wiki
Jump to navigation Jump to search
m (Language source block, instead of pre)
m (Text replacement - "</source>" to "</syntaxhighlight>")
Line 1: Line 1:
'''Split-compose''' is a [[tacit]] construct, used to pre-process its argument(s) with the left and right-most operand before applying the middle operand between the result. Given functions <source lang=apl inline>f</source>, <source lang=apl inline>g</source>, and <source lang=apl inline>h</source>, the split composition on arguments <source lang=apl inline>x</source> and <source lang=apl inline>y</source> is defined as <source lang=apl inline>(f x) g (h y)</source>.
'''Split-compose''' is a [[tacit]] construct, used to pre-process its argument(s) with the left and right-most operand before applying the middle operand between the result. Given functions <source lang=apl inline>f</syntaxhighlight>, <source lang=apl inline>g</syntaxhighlight>, and <source lang=apl inline>h</syntaxhighlight>, the split composition on arguments <source lang=apl inline>x</syntaxhighlight> and <source lang=apl inline>y</syntaxhighlight> is defined as <source lang=apl inline>(f x) g (h y)</syntaxhighlight>.


The name was introduced by the [[I|I language]], where it is represented with <source lang=apl inline>O</source>, a higher-order function that applies first to the middle [[function]] and then the two outer functions (<source lang=apl inline>O</source> also represents the [[Over]] operator). It doesn't appear as a primitive in any APL, nor can it, because it is a [[composition]] of three functions, while a [[Function composition|compositional operator]] can take no more than two [[operands]]. This situation is identical to that of the [[fork]]. Both split-compose and fork can be constructed using two companion operators, tying together the three involved functions.
The name was introduced by the [[I|I language]], where it is represented with <source lang=apl inline>O</syntaxhighlight>, a higher-order function that applies first to the middle [[function]] and then the two outer functions (<source lang=apl inline>O</syntaxhighlight> also represents the [[Over]] operator). It doesn't appear as a primitive in any APL, nor can it, because it is a [[composition]] of three functions, while a [[Function composition|compositional operator]] can take no more than two [[operands]]. This situation is identical to that of the [[fork]]. Both split-compose and fork can be constructed using two companion operators, tying together the three involved functions.


In [[Extended Dyalog APL]] and [[dzaima/APL]], the construct can be formed using [[Reverse Compose]] (<code>⍛</code>) and [[Compose]] (<code>∘</code>). In this example, we multiply the [[interval]] (integers up until) of the left argument, with the [[Magnitude]] of the right:
In [[Extended Dyalog APL]] and [[dzaima/APL]], the construct can be formed using [[Reverse Compose]] (<code>⍛</code>) and [[Compose]] (<code>∘</code>). In this example, we multiply the [[interval]] (integers up until) of the left argument, with the [[Magnitude]] of the right:
Line 7: Line 7:
       5 ⍳⍛×∘| 5 ¯8 ¯2 ¯5 3
       5 ⍳⍛×∘| 5 ¯8 ¯2 ¯5 3
5 16 6 20 15
5 16 6 20 15
</source>
</syntaxhighlight>
This is evaluated as <source lang=apl inline>(⍳5) × (|5 ¯8 ¯2 ¯5 3)</source>. A further example concatenates the reciprocal of the left argument with the negation of the right:
This is evaluated as <source lang=apl inline>(⍳5) × (|5 ¯8 ¯2 ¯5 3)</syntaxhighlight>. A further example concatenates the reciprocal of the left argument with the negation of the right:
<source lang=apl>
<source lang=apl>
       2(,⍨∘÷⍨∘-⍨⍨)4
       2(,⍨∘÷⍨∘-⍨⍨)4
0.5 ¯4
0.5 ¯4
</source>
</syntaxhighlight>
This is evaluated as <source lang=apl inline>(÷2) × (-4)</source>.
This is evaluated as <source lang=apl inline>(÷2) × (-4)</syntaxhighlight>.
== Alternatives ==
== Alternatives ==


In dialects that lack Reverse Compose (and even Compose), split-compose can be written either by defining the missing operator(s), or as a single derived function or [[fork]], if this is supported. For example, in [[Dyalog APL]] the expression can be formed with Compose and [[Commute]] (<source lang=apl inline>⍨</source>) as <source lang=apl inline>g⍨∘f⍨∘h</source>:
In dialects that lack Reverse Compose (and even Compose), split-compose can be written either by defining the missing operator(s), or as a single derived function or [[fork]], if this is supported. For example, in [[Dyalog APL]] the expression can be formed with Compose and [[Commute]] (<source lang=apl inline>⍨</syntaxhighlight>) as <source lang=apl inline>g⍨∘f⍨∘h</syntaxhighlight>:
<source lang=apl>
<source lang=apl>
       5 ×⍨∘⍳⍨∘| 5 ¯8 ¯2 ¯5 3
       5 ×⍨∘⍳⍨∘| 5 ¯8 ¯2 ¯5 3
Line 22: Line 22:
       2(,⍨∘÷⍨∘-)4
       2(,⍨∘÷⍨∘-)4
0.5 ¯4
0.5 ¯4
</source>
</syntaxhighlight>
Note that <source lang=apl inline>g∘h⍨∘f⍨</source> applies <source lang=apl inline>f</source> before <source lang=apl inline>h</source> which can matter for functions with side effects. For example, consider the following where <source lang=apl inline>'x' f⍛g∘h 'y'</source> would print <code>hfg</code>:
Note that <source lang=apl inline>g∘h⍨∘f⍨</syntaxhighlight> applies <source lang=apl inline>f</syntaxhighlight> before <source lang=apl inline>h</syntaxhighlight> which can matter for functions with side effects. For example, consider the following where <source lang=apl inline>'x' f⍛g∘h 'y'</syntaxhighlight> would print <code>hfg</code>:
<source lang=apl>
<source lang=apl>
       f←{⍞←⊃⎕SI}
       f←{⍞←⊃⎕SI}
Line 32: Line 32:
       'x' g∘h⍨∘f⍨ 'y'
       'x' g∘h⍨∘f⍨ 'y'
fhg
fhg
</source>
</syntaxhighlight>
The equivalent fork is <source lang=apl inline>f⍤⊣ g h⍤⊢</source>, for example:
The equivalent fork is <source lang=apl inline>f⍤⊣ g h⍤⊢</syntaxhighlight>, for example:
<source lang=apl>
<source lang=apl>
       5 (⍳⍤⊣×|⍤⊢) 5 ¯8 ¯2 ¯5 3
       5 (⍳⍤⊣×|⍤⊢) 5 ¯8 ¯2 ¯5 3
Line 39: Line 39:
       2(÷⍤⊣,-⍤⊢)4
       2(÷⍤⊣,-⍤⊢)4
0.5 ¯4
0.5 ¯4
</source>
</syntaxhighlight>
{{APL syntax}}[[Category:Primitive operators]]
{{APL syntax}}[[Category:Primitive operators]]

Revision as of 10:39, 11 September 2022

Split-compose is a tacit construct, used to pre-process its argument(s) with the left and right-most operand before applying the middle operand between the result. Given functions <source lang=apl inline>f</syntaxhighlight>, <source lang=apl inline>g</syntaxhighlight>, and <source lang=apl inline>h</syntaxhighlight>, the split composition on arguments <source lang=apl inline>x</syntaxhighlight> and <source lang=apl inline>y</syntaxhighlight> is defined as <source lang=apl inline>(f x) g (h y)</syntaxhighlight>.

The name was introduced by the I language, where it is represented with <source lang=apl inline>O</syntaxhighlight>, a higher-order function that applies first to the middle function and then the two outer functions (<source lang=apl inline>O</syntaxhighlight> also represents the Over operator). It doesn't appear as a primitive in any APL, nor can it, because it is a composition of three functions, while a compositional operator can take no more than two operands. This situation is identical to that of the fork. Both split-compose and fork can be constructed using two companion operators, tying together the three involved functions.

In Extended Dyalog APL and dzaima/APL, the construct can be formed using Reverse Compose () and Compose (). In this example, we multiply the interval (integers up until) of the left argument, with the Magnitude of the right: <source lang=apl>

     5 ⍳⍛×∘| 5 ¯8 ¯2 ¯5 3

5 16 6 20 15 </syntaxhighlight> This is evaluated as <source lang=apl inline>(⍳5) × (|5 ¯8 ¯2 ¯5 3)</syntaxhighlight>. A further example concatenates the reciprocal of the left argument with the negation of the right: <source lang=apl>

     2(,⍨∘÷⍨∘-⍨⍨)4

0.5 ¯4 </syntaxhighlight> This is evaluated as <source lang=apl inline>(÷2) × (-4)</syntaxhighlight>.

Alternatives

In dialects that lack Reverse Compose (and even Compose), split-compose can be written either by defining the missing operator(s), or as a single derived function or fork, if this is supported. For example, in Dyalog APL the expression can be formed with Compose and Commute (<source lang=apl inline>⍨</syntaxhighlight>) as <source lang=apl inline>g⍨∘f⍨∘h</syntaxhighlight>: <source lang=apl>

     5 ×⍨∘⍳⍨∘| 5 ¯8 ¯2 ¯5 3

5 16 6 20 15

     2(,⍨∘÷⍨∘-)4

0.5 ¯4 </syntaxhighlight> Note that <source lang=apl inline>g∘h⍨∘f⍨</syntaxhighlight> applies <source lang=apl inline>f</syntaxhighlight> before <source lang=apl inline>h</syntaxhighlight> which can matter for functions with side effects. For example, consider the following where <source lang=apl inline>'x' f⍛g∘h 'y'</syntaxhighlight> would print hfg: <source lang=apl>

     f←{⍞←⊃⎕SI}
     g←{⍞←⊃⎕SI}
     h←{⍞←⊃⎕SI}
     'x' g⍨∘f⍨∘h 'y'

hfg

     'x' g∘h⍨∘f⍨ 'y'

fhg </syntaxhighlight> The equivalent fork is <source lang=apl inline>f⍤⊣ g h⍤⊢</syntaxhighlight>, for example: <source lang=apl>

     5 (⍳⍤⊣×|⍤⊢) 5 ¯8 ¯2 ¯5 3

5 16 6 20 15

     2(÷⍤⊣,-⍤⊢)4

0.5 ¯4 </syntaxhighlight>

APL syntax [edit]
General Comparison with traditional mathematicsPrecedenceTacit programming (Train, Hook, Split composition)
Array Numeric literalStringStrand notationObject literalArray notation (design considerations)
Function ArgumentFunction valenceDerived functionDerived operatorNiladic functionMonadic functionDyadic functionAmbivalent functionDefined function (traditional)DfnFunction train
Operator OperandOperator valenceTradopDopDerived operator
Assignment MultipleIndexedSelectiveModified
Other Function axisBracket indexingBranchStatement separatorQuad nameSystem commandUser commandKeywordDot notationFunction-operator overloadingControl structureComment