Split composition: Difference between revisions

Jump to navigation Jump to search
2,106 bytes added ,  08:45, 23 September 2022
m
no edit summary
(Created page with "'''Split-compose''' is a point-free construct, used to pre-process the argument(s) with the left, and right-most operand before applying the middle operand between the result....")
 
mNo edit summary
 
(15 intermediate revisions by 4 users not shown)
Line 1: Line 1:
'''Split-compose''' is a point-free construct, used to pre-process the argument(s) with the left, and right-most operand before applying the middle operand between the result.
{{Glyphbox|f⍛g∘h}}[[File:Split_composition.png|frameless|right|200px]]
'''Split composition''' is a [[tacit]] pattern, used to pre-process argument(s) with the outer-most operands before applying the middle operand between the result. Given functions <syntaxhighlight lang=apl inline>f</syntaxhighlight>, <syntaxhighlight lang=apl inline>g</syntaxhighlight>, and <syntaxhighlight lang=apl inline>h</syntaxhighlight>, a split composition on arguments <syntaxhighlight lang=apl inline>x</syntaxhighlight> and <syntaxhighlight lang=apl inline>y</syntaxhighlight> is defined as <syntaxhighlight lang=apl inline>(f x) g (h y)</syntaxhighlight>.


It's definition is specified as <source lang=apl inline>(F x) G (H y)</source>.
This construct was introduced by the [[I|I language]] as "split-compose", where it is represented with <syntaxhighlight lang=apl inline>O</syntaxhighlight> which also represents the [[Over]] operator - as it too is a split composition with identical outer operands.  


In BQN, the construct can be formed using [[Before]] <code>(⊸)</code> and [[After]] <code>(⟜)</code>, two [[Function composition|compositional]] [[operator]]s. In this example, we multiply the range of the left argument, with the absolute value of the right.
This doesn't appear as a primitive in any APL, nor can it, because it [[composition|composes]] 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 compositions and forks can be constructed using companion operators, tying together the three involved functions.
    5 ↕⊸×⟜| 5‿¯8‿¯2‿¯5‿3
⟨ 0 8 4 15 12 ⟩


[[Monadic]]ally, the right argument can be [[selfie|duplicated]] and split-compose will be applied asymmetrically, similar to [[hook]]
In [[Extended Dyalog APL]] and [[dzaima/APL]], a split composition 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:
    +´⊸÷⟜≠ ↕10
<syntaxhighlight lang=apl>
4.5
      5 ⍳⍛×∘| 5 ¯8 ¯2 ¯5 3
# This is evaluated as (↕10) +´⊸÷⟜≢ ↕10
5 16 6 20 15
</syntaxhighlight>
This is evaluated as <syntaxhighlight 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:
<syntaxhighlight lang=apl>
      2 ÷⍛,- 4
0.5 ¯4
</syntaxhighlight>
This is evaluated as <syntaxhighlight lang=apl inline>(÷2) × (-4)</syntaxhighlight>.
== Alternatives ==


Monadically, split-compose is precisely equivalent to a [[fork]].
In dialects that lack Reverse Compose (and even Compose), split compositions can be denoted 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 pattern can be formed with Compose and [[Commute]] (<syntaxhighlight lang=apl inline>⍨</syntaxhighlight>) as <syntaxhighlight lang=apl inline>g⍨∘f⍨∘h</syntaxhighlight>:
 
<syntaxhighlight lang=apl>
    (+´÷≠) ↕10
      5 ×⍨∘⍳⍨∘| 5 ¯8 ¯2 ¯5 3
4.5
5 16 6 20 15
 
      2(,⍨∘÷⍨∘-)4
 
0.5 ¯4
 
</syntaxhighlight>
In dialects that lack Before, split-compose can be defined differently.
Note that <syntaxhighlight lang=apl inline>g∘h⍨∘f⍨</syntaxhighlight> applies <syntaxhighlight lang=apl inline>f</syntaxhighlight> before <syntaxhighlight lang=apl inline>h</syntaxhighlight> which can matter for functions with side effects. For example, consider the following where <syntaxhighlight lang=apl inline>'x' f⍛g∘h 'y'</syntaxhighlight> would print <code>hfg</code>:
 
<syntaxhighlight lang=apl>
In [[Dyalog APL]] you may form the expression with [[Beside]] <code>()</code> and [[Commute]] <code>(⍨)</code>
      f←{⍞←⊃⎕SI}
 
      g←{⍞←⊃⎕SI}
g∘h⍨∘f⍨
      h←{⍞←⊃⎕SI}
 
      'x' g⍨∘f⍨∘h 'y'
g⍨∘f⍨∘h⍨⍨
hfg
 
      'x' g∘h⍨∘f⍨ 'y'
For example:
fhg
       ÷⍨∘(+/)⍨∘≢⍨⍨ ⍳10
</syntaxhighlight>
4.5
The equivalent fork is <syntaxhighlight lang=apl inline>f⍤⊣ g h⍤⊢</syntaxhighlight>, for example:
 
<syntaxhighlight lang=apl>
Whilst these expressions will return the same results (if the functions f,g, & h are pure) the evaluation order is not identical.
       5 (⍳⍤⊣×|⍤⊢) 5 ¯8 ¯2 ¯5 3
 
5 16 6 20 15
And (most commonly) as a fork:
      2(÷⍤⊣,-⍤⊢)4
 
0.5 ¯4
f⍤⊣ g h⍤⊢
</syntaxhighlight>
{{APL syntax}}[[Category:Primitive operators]]
26

edits

Navigation menu