Hook: Difference between revisions

From APL Wiki
Jump to navigation Jump to search
(Style changes to use APL instead of language-specific terminology)
m (Text replacement - "first-class function" to "first-class function")
 
(8 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{Built-ins|Hooks|⍛|⍩}} are asymmetrical forms of [[function composition]] that first apply one of the composed [[function]]s to one [[argument]], then applies the other function to one argument and the result. [[Kap]] has the two [[operator]]s [[Beside|Compose]] (<syntaxhighlight lang=apl inline>∘</syntaxhighlight>) and [[Inverse compose]] (<syntaxhighlight lang=apl inline>⍛</syntaxhighlight>). [[BQN]] has Before (<code>⊸</code>) and After (<code>⟜</code>), which also serve the purpose of the [[Bind]] operator. In [[J]], a 2-[[train]] is a hook, while [[I]] adds the mirror image to give two functions (I has [[first-class function]]s but no operators) hook (<code>h</code>) and backhook (<code>H</code>).
Hook as an operator first appeared in [[A Dictionary of APL]] as [[Withe]] (<syntaxhighlight lang=apl inline>⍩</syntaxhighlight>). However, [[Ken Iverson|Iverson]] and [[Eugene McDonnell|McDonnell]]'s paper ''Phrasal Forms'', which introduced [[train]]s<ref>[[Ken Iverson]] and [[Eugene McDonnell]]. [http://www.jsoftware.com/papers/fork.htm Phrasal forms] at [[APL89]].</ref>, proposed hook as the meaning of a 2-train, and this was soon included in [[J]]. This definition specifies that <syntaxhighlight lang=j inline>(F G) y</syntaxhighlight> is <syntaxhighlight lang=j inline>y F G y</syntaxhighlight> and <syntaxhighlight lang=j inline>x (F G) y</syntaxhighlight> is <syntaxhighlight lang=j inline>x F G y</syntaxhighlight>. However, [[Roger Hui]] later opined that this definition was better suited to a dyadic operator (which could be denoted <syntaxhighlight lang=j inline>h.</syntaxhighlight>) than an element of syntax,<ref>[[Roger Hui]]. [https://code.jsoftware.com/wiki/Essays/Hook_Conjunction%3F Hook Conjunction?]. J Wiki essays. 2006. Accessed 2021-02-08.</ref> and defined the 2-train to represent [[Atop]] instead when he led the introduction of trains to [[Dyalog APL]]. By that time, Dyalog had long had the [[Beside]] (originally called ''Compose'') operator which is equivalent to <syntaxhighlight lang=j inline>x F h. G y</syntaxhighlight>, that is, the dyadic case. The monadic functionality can be achieved using [[Commute]] as <syntaxhighlight lang=apl inline>F∘G⍨y</syntaxhighlight> and the full [[ambivalent]] function can be written as <syntaxhighlight lang=apl inline>F∘G⍨⍨</syntaxhighlight>.
[[File:Hooks.png|thumb|right|Hook operators in [[BQN]]]]
[[File:Hooks.png|thumb|right|Hook operators in [[BQN]]]]
In order to maintain symmetry, [[Kap]] changes the meaning of <syntaxhighlight lang=apl inline>∘</syntaxhighlight> to be a proper hook, and thus aligns itself with [[I]] and [[BQN]], which also have two hooks. Kap defines Compose (<syntaxhighlight lang=apl inline>∘</syntaxhighlight>) to be the dyadic operator <syntaxhighlight lang=apl inline>{⍺←⍵ ⋄ ⍺ ⍺⍺ ⍵⍵ ⍵}</syntaxhighlight> and Inverse Compose (<syntaxhighlight lang=apl inline>⍛</syntaxhighlight>) to be <syntaxhighlight lang=apl inline>{⍺←⍵ ⋄ (⍺⍺ ⍺) ⍵⍵ ⍵}</syntaxhighlight>. In the dyadic case these operators are identical to [[Beside]] and [[Reverse Compose]] respectively, but in the monadic case, <syntaxhighlight lang=apl inline>∘</syntaxhighlight> differs from Beside because the argument is used twice: the second function application takes it as an argument directly in addition to the result of the first function application.


A '''hook''' is an asymmetrical form of function composition that first applies one of the composed functions to one argument, then applies the other function to one argument and the result. In [[J]], a 2-[[train]] is a hook, while [[I]] adds the mirror image to give two functions (I has first-class functions but no operators) hook (<code>h</code>) and backhook (<code>H</code>). [[BQN]] uses two [[operator]]s Before (<code>⊸</code>) and After (<code>⟜</code>), which also serve the purpose of the [[Bind]] operator.
The two hooks can be used together to form a [[split-compose]] construct:
 
<pre>
The meaning of 2-train as hook was first proposed in [[Ken Iverson|Iverson]] and [[Eugene McDonnell|McDonnell]]'s paper ''Phrasal Forms'' introducing [[train]]s<ref>[[Ken Iverson]] and [[Eugene McDonnell]]. [http://www.jsoftware.com/papers/fork.htm Phrasal forms] at [[APL89]].</ref>, and soon included in [[J]]. This definition specifies that <source lang=j inline>(F G) y</source> is <source lang=j inline>y F G y</source> and <source lang=j inline>x (F G) y</source> is <source lang=j inline>x F G y</source>. However, [[Roger Hui]] later opined that this definition was better suited to a dyadic operator than an element of syntax,<ref>[[Roger Hui]]. [https://code.jsoftware.com/wiki/Essays/Hook_Conjunction%3F Hook Conjunction?]. J Wiki essays. 2006. Accessed 2021-02-08.</ref> and defined to 2-train to represent [[Atop]] instead when he led the introduction of trains to [[Dyalog APL]].
     3 ¯1 4 ×⍛×∘| ¯2 ¯7 1
 
2 ¯7 1
In [[I]] and [[BQN]], there are two hooks in order to maintain symmetry: for example, BQN defines Before (<code>⊸</code>) to be the dyadic operator <code>{(𝔽𝕨⊣𝕩)𝔾𝕩}</code> ("<code>𝔾</code>'s left argument comes from <code>𝔽</code>") and After (<code>⟜</code>) to be <code>{(𝕨⊣𝕩)𝔽𝔾𝕩}</code> ("<code>𝔽</code>'s right argument comes from <code>𝔾</code>"). In the dyadic case these functions are identical to [[Reverse Compose]] and [[Beside]] respectively, but in the monadic case they differ because the argument is used twice: the second function application takes it as an argument directly in addition to the result of the first function application.
</pre>{{Works in|[[Kap]]}}
 
This definition behaves differently that the Compose-based one when only one argument is given; in that case, it becomes a monadic 3-[[train]].
Like [[Reverse Compose]], the two hooks can be used together to form a [[split-compose]] construct.
<source>
     3‿¯1‿4 ×⊸×⟜| ¯2‿¯7‿1
2 ¯7 1
</source>{{Works in|[[BQN]]}}
This definition behaves differently that the Compose-based one when only one argument is given: in that case, it becomes a monadic 3-[[train]].


The name "hook" was chosen based on the hook shape of a function call diagram such as the one below, taken from ''Phrasal Forms''.
The name "hook" was chosen based on the hook shape of a function call diagram such as the one below, taken from ''Phrasal Forms''.
<source>
<pre>
⍺(fg)⍵ ←→ ⍺fg⍵
⍺(fg)⍵ ←→ ⍺fg⍵


Line 23: Line 21:
         \
         \
         ⍵
         ⍵
</source>
</pre>


== See also ==
== See also ==
Line 32: Line 30:


* J [https://www.jsoftware.com/help/dictionary/dictf.htm Dictionary], [https://code.jsoftware.com/wiki/Vocabulary/hook NuVoc]
* J [https://www.jsoftware.com/help/dictionary/dictf.htm Dictionary], [https://code.jsoftware.com/wiki/Vocabulary/hook NuVoc]
* [https://mlochbaum.github.io/BQN/tutorial/combinator.html#before-and-after BQN tutorials]
* [https://mlochbaum.github.io/BQN/doc/hook.html BQN]


== References ==
== References ==
<references />
<references />
{{APL built-ins}}[[Category:Primitive operators]]
{{APL syntax}}[[Category:Primitive operators]]

Latest revision as of 02:09, 6 September 2024

Hooks (, ) are asymmetrical forms of function composition that first apply one of the composed functions to one argument, then applies the other function to one argument and the result. Kap has the two operators Compose () and Inverse compose (). BQN has Before () and After (), which also serve the purpose of the Bind operator. In J, a 2-train is a hook, while I adds the mirror image to give two functions (I has first-class functions but no operators) hook (h) and backhook (H).

Hook as an operator first appeared in A Dictionary of APL as Withe (). However, Iverson and McDonnell's paper Phrasal Forms, which introduced trains[1], proposed hook as the meaning of a 2-train, and this was soon included in J. This definition specifies that (F G) y is y F G y and x (F G) y is x F G y. However, Roger Hui later opined that this definition was better suited to a dyadic operator (which could be denoted h.) than an element of syntax,[2] and defined the 2-train to represent Atop instead when he led the introduction of trains to Dyalog APL. By that time, Dyalog had long had the Beside (originally called Compose) operator which is equivalent to x F h. G y, that is, the dyadic case. The monadic functionality can be achieved using Commute as F∘G⍨y and the full ambivalent function can be written as F∘G⍨⍨.

Hook operators in BQN

In order to maintain symmetry, Kap changes the meaning of to be a proper hook, and thus aligns itself with I and BQN, which also have two hooks. Kap defines Compose () to be the dyadic operator {⍺←⍵ ⋄ ⍺ ⍺⍺ ⍵⍵ ⍵} and Inverse Compose () to be {⍺←⍵ ⋄ (⍺⍺ ⍺) ⍵⍵ ⍵}. In the dyadic case these operators are identical to Beside and Reverse Compose respectively, but in the monadic case, differs from Beside because the argument is used twice: the second function application takes it as an argument directly in addition to the result of the first function application.

The two hooks can be used together to form a split-compose construct:

    3 ¯1 4 ×⍛×∘| ¯2 ¯7 1
2 ¯7 1
Works in: Kap

This definition behaves differently that the Compose-based one when only one argument is given; in that case, it becomes a monadic 3-train.

The name "hook" was chosen based on the hook shape of a function call diagram such as the one below, taken from Phrasal Forms.

⍺(fg)⍵ ←→ ⍺fg⍵

     f
    / \
   ⍺   g
        \
         ⍵

See also

External links

References

  1. Ken Iverson and Eugene McDonnell. Phrasal forms at APL89.
  2. Roger Hui. Hook Conjunction?. J Wiki essays. 2006. Accessed 2021-02-08.
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