Leading axis theory: Difference between revisions

Jump to navigation Jump to search
1,299 bytes added ,  21:46, 10 September 2022
m
Text replacement - "</source>" to "</syntaxhighlight>"
m (Text replacement - "</source>" to "</syntaxhighlight>")
 
(11 intermediate revisions by 4 users not shown)
Line 1: Line 1:
'''Leading axis theory''', or the '''leading axis model''', is an approach to array language design and use that emphasizes working with arrays by manipulating their [[cell]]s and mapping functions over leading [[Axis|axes]] implicitly using [[function rank]] or explicitly using the [[Rank operator]]. It was initially developed in [[SHARP APL]] in the early 1980s and is now a major feature of [[J]] and [[Dyalog APL]], as well as languages influenced by these. The name "leading axis" comes from the [[frame]], which consists of leading axes of an array, the related concept of [[leading axis agreement]], which extends [[scalar]] [[conformability]], and the emphasis on first axis forms of functions while deprecating or discarding other [[function axis|choices of axis]].
'''Leading axis theory''', or the '''leading axis model''', is an approach to array language design and use that emphasizes working with arrays by manipulating their [[cell]]s and mapping functions over leading [[Axis|axes]] implicitly using [[function rank]] or explicitly using the [[Rank (operator)|Rank operator]]. It was initially developed in [[SHARP APL]] in the early 1980s and is now a major feature of [[J]] and [[Dyalog APL]], as well as languages influenced by these. The name "leading axis" comes from the [[frame]], which consists of leading axes of an array, the related concept of [[leading axis agreement]], which extends [[scalar]] [[conformability]], and the emphasis on first axis forms of functions while deprecating or discarding other [[function axis|choices of axis]].


== Features ==
== Features ==
Line 5: Line 5:
The leading axis theory as a complete model of programming is best exemplified by [[J]], since it was designed entirely using the theory from the start. While various APLs have developed or adopted features of the leading axis model, [[backwards compatibility]] requirements can prevent them from making certain changes to align with the theory.
The leading axis theory as a complete model of programming is best exemplified by [[J]], since it was designed entirely using the theory from the start. While various APLs have developed or adopted features of the leading axis model, [[backwards compatibility]] requirements can prevent them from making certain changes to align with the theory.


J defines all one-dimensional functions to work on the first [[axis]], that is, to manipulate [[major cell]]s of their arguments. In this way it unifies APL's pairs of first- and last-axis functions and operators including [[Reverse]], [[Rotate]], [[Replicate]], [[Expand]], [[Reduce]], and [[Scan]]. J retains two functions corresponding to <source lang=apl inline>,</source> and <source lang=apl inline>⍪</source>, with <source lang=j inline>,</source> as [[Ravel]] and [[Catenate First]] and <source lang=j inline>,.</source> for second- (rather than last-) axis forms of these functions; <source lang=j inline>,.</source> is identical to <source lang=j inline>,"_1</source> (which transliterates to APL <source lang=apl inline>,⍤¯1</source>) in both valences.
J defines all one-dimensional functions to work on the first [[axis]], that is, to manipulate [[major cell]]s of their arguments. In this way it unifies APL's pairs of first- and last-axis functions and operators including [[Reverse]], [[Rotate]], [[Replicate]], [[Expand]], [[Reduce]], and [[Scan]]. J retains two functions corresponding to <syntaxhighlight lang=apl inline>,</syntaxhighlight> and <syntaxhighlight lang=apl inline>⍪</syntaxhighlight>, with <syntaxhighlight lang=j inline>,</syntaxhighlight> as [[Ravel]] and [[Catenate First]] and <syntaxhighlight lang=j inline>,.</syntaxhighlight> for second- (rather than last-) axis forms of these functions; <syntaxhighlight lang=j inline>,.</syntaxhighlight> is identical to <syntaxhighlight lang=j inline>,"_1</syntaxhighlight> (which transliterates to APL <syntaxhighlight lang=apl inline>,⍤¯1</syntaxhighlight>) in both valences.


J also extends [[Rotate]] so that it can work on multiple leading axes rather than a single axis: additional values in the left argument apply to leading axes of the right in order. This aligns Rotate with the [[SHARP APL]] extensions to [[Take]], [[Drop]], and [[Squad]] allowing short left arguments: in each case the left argument is a [[vector]] corresponding to axes of the right argument starting at the first.
J also extends [[Rotate]] so that it can work on multiple leading axes rather than a single axis: additional values in the left argument apply to leading axes of the right in order. This aligns Rotate with the [[SHARP APL]] extensions to [[Take]], [[Drop]], and [[Squad]] allowing short left arguments: in each case the left argument is a [[vector]] corresponding to axes of the right argument starting at the first.
Line 15: Line 15:
== Adoption in APL ==
== Adoption in APL ==


Because APL was designed before the leading axis model was developed, many APL primitives do not naturally adhere to the theory and some are not compatible with it at all. The following table describes how functions and operators that act on specific axes of their arguments (omitting for example [[Enclose]] and [[Match]] which apply to entire arrays) interact with leading axis theory.
Because APL was designed before the leading axis model was developed, many APL primitives do not naturally adhere to the theory and some are not [[compatible]] with it at all. The following table describes how functions and operators that act on specific axes of their arguments (omitting for example [[Enclose]] and [[Match]] which apply to entire arrays) interact with leading axis theory.


{|class=wikitable
{|class=wikitable
! Compatibility              !! Functions
! Compatibility              !! Functions
|-
|-
| Already compatible        || [[Grade]] (<source lang=apl inline>⍋</source>, <source lang=apl inline>⍒</source>), [[Decode]] (<source lang=apl inline>⊥</source>), [[Encode]] (<source lang=apl inline>⊤</source>)
| Already compatible        || [[Grade]] (<syntaxhighlight lang=apl inline>⍋</syntaxhighlight>, <syntaxhighlight lang=apl inline>⍒</syntaxhighlight>), [[Decode]] (<syntaxhighlight lang=apl inline>⊥</syntaxhighlight>), [[Encode]] (<syntaxhighlight lang=apl inline>⊤</syntaxhighlight>)
|-
|-
| Use first axis form only  || [[Reverse]], [[Rotate]] (<source lang=apl inline>⊖</source>), [[Replicate]], [[Reduce]] (<source lang=apl inline>⌿</source>), [[Expand]], [[Scan]] (<source lang=apl inline>⍀</source>), [[Catenate]] (<source lang=apl inline>⍪</source>)
| Use first axis form only  || [[Reverse]], [[Rotate]] (<syntaxhighlight lang=apl inline>⊖</syntaxhighlight>), [[Replicate]], [[Reduce]] (<syntaxhighlight lang=apl inline>⌿</syntaxhighlight>), [[Expand]], [[Scan]] (<syntaxhighlight lang=apl inline>⍀</syntaxhighlight>), [[Catenate]] (<syntaxhighlight lang=apl inline>⍪</syntaxhighlight>)
|-
|-
| Extendible to leading axes || [[Take]] (<source lang=apl inline>↑</source>), [[Drop]] (<source lang=apl inline>↓</source>), [[indexing]] (<source lang=apl inline>⌷</source>), [[scalar dyadic]]s, [[Unique]] (<source lang=apl inline>∪</source> or <source lang=apl inline>↑</source>) and most [[set function]]s (<source lang=apl inline>⍳∪∩~</source>)
| Extendible to leading axes || [[Take]] (<syntaxhighlight lang=apl inline>↑</syntaxhighlight>), [[Drop]] (<syntaxhighlight lang=apl inline>↓</syntaxhighlight>), [[Squad Indexing]] (<syntaxhighlight lang=apl inline>⌷</syntaxhighlight>), [[scalar dyadic]]s, [[Unique]] (<syntaxhighlight lang=apl inline>∪</syntaxhighlight> or <syntaxhighlight lang=apl inline>↑</syntaxhighlight>) and most [[set function]]s (<syntaxhighlight lang=apl inline>⍳∪∩~</syntaxhighlight>)
|-
|-
| Incompatible              || [[Split]] (<source lang=apl inline>↓</source>), [[First]] (<source lang=apl inline>↑</source> or <source lang=apl inline>⊃</source>), [[Membership]] (<source lang=apl inline>∊</source>), [[Partition]] (<source lang=apl inline>⊂</source> and <source lang=apl inline>⊆</source>)
| Incompatible              || [[Split]] (<syntaxhighlight lang=apl inline>↓</syntaxhighlight>), [[First]] (<syntaxhighlight lang=apl inline>↑</syntaxhighlight> or <syntaxhighlight lang=apl inline>⊃</syntaxhighlight>), [[Membership]] (<syntaxhighlight lang=apl inline>∊</syntaxhighlight>), [[Partition]] (<syntaxhighlight lang=apl inline>⊂</syntaxhighlight> and <syntaxhighlight lang=apl inline>⊆</syntaxhighlight>)
|-
|-
| Unclear                    || [[Find]] (<source lang=apl inline>⍷</source>)
| Unclear                    || [[Find]] (<syntaxhighlight lang=apl inline>⍷</syntaxhighlight>)
|-
|-
| Designed for leading axes  || [[Rank operator]] (<source lang=apl inline>⍤</source>), [[Tally]] (<source lang=apl inline>≢</source>), [[Interval Index]] (<source lang=apl inline>⍸</source>), [[Key]] (<source lang=apl inline>⌸</source>), [[Raze]] (<source lang=apl inline>⊃</source>)
| Designed for leading axes  || [[Rank operator]] (<syntaxhighlight lang=apl inline>⍤</syntaxhighlight>), [[Tally]] (<syntaxhighlight lang=apl inline>≢</syntaxhighlight>), [[Interval Index]] (<syntaxhighlight lang=apl inline>⍸</syntaxhighlight>), [[Key]] (<syntaxhighlight lang=apl inline>⌸</syntaxhighlight>), [[Raze]] (<syntaxhighlight lang=apl inline>⊃</syntaxhighlight>)
|}
|}


Backwards-compatible language changes are only effective for functions which are extendible to leading axes. The following extensions have been made in order to support leading axis theory:
In addition to these, the [[Rank operator]] and [[scalar dyadic]]s can be extended with [[leading axis agreement]], so that arguments with different-length frames can match as long as one frame is a prefix of the other. The original introduction of Rank had only an analogue of [[scalar extension]], where an argument with an empty frame is repeated to pair it with an argument with a non-empty frame. The following extensions have been made in order to support leading axis theory:


{|class=wikitable
{|class=wikitable
! Functions                                !! [[SHARP APL]]      !! [[Dyalog APL]]      !!style="min-width:5em"| [[A+]]  !!style="min-width:5em"| [[J]]
! Functions                                !! [[SHARP APL]]      !! [[Dyalog APL]]      !!style="min-width:5em"| [[A+]]  !!style="min-width:5em"| [[J]]    !!style="min-width:5em"| [[BQN]]
|-
|-
| [[Take]], [[Drop]]                      || {{Yes|19.0}}        || {{Yes|13.0}}        || {{Yes}}                        || {{Yes}}
| [[Take]], [[Drop]]                      || {{Yes|19.0}}        || {{Yes|13.0}}        || {{Yes}}                        || {{Yes}}                        || {{Yes}}
|-
|-
| [[Indexing]] function                   || {{Yes|19.0}}        || {{Yes|13.0}}        || {{Yes}}                        || {{Yes}}
| [[Squad Indexing|Indexing]] function     || {{Yes|19.0}}        || {{Yes|13.0}}        || {{Yes}}                        || {{Yes}}                        || {{Yes}}
|-
|-
| [[Bracket indexing]]                    || {{No}}              || {{No}}              || {{Yes}}                        ||style="text-align:center;"| N/A
| [[Bracket indexing]]                    || {{No}}              || {{No}}              || {{Yes}}                        ||style="text-align:center;"| N/A  ||style="text-align:center;"| N/A
|-
|-
| [[Scalar dyadic]]s                      || {{Yes}}             || {{No}}              || {{No}}                        || {{Yes}}
| [[Scalar dyadic]]s                      || {{No}}             || {{No}}              || {{No}}                        || {{Yes}}                        || {{Yes}}
|-
|-
| [[Index Of]]                            || {{No|Incompatible}} || {{Yes|14.0}}        || {{Yes}}                        || {{Yes}}
| [[Index Of]]                            || {{No|Incompatible}} || {{Yes|14.0}}        || {{Yes}}                        || {{Yes}}                        || {{Yes}}
|-
|-
| [[Membership]]                          || {{No|Incompatible}} || {{No|Incompatible}} || {{Yes}}                        || {{Yes}}
| [[Membership]]                          || {{No|Incompatible}} || {{No|Incompatible}} || {{Yes}}                        || {{Yes}}                        || {{Yes}}
|-
|-
| [[Unique]]                              || {{Yes}}            || {{Yes|17.0}}        ||style="text-align:center;"| N/A || {{Yes}}
| [[Unique]]                              || {{Yes}}            || {{Yes|17.0}}        ||style="text-align:center;"| N/A || {{Yes}}                        || {{Yes}}
|-
|-
| [[Union]], [[Intersection]], [[Without]] || {{No}}              || {{No}}              ||style="text-align:center;"| N/A || {{Yes}}
| [[Union]], [[Intersection]], [[Without]] || {{No}}              || {{No}}              ||style="text-align:center;"| N/A || {{Yes}}                         ||style="text-align:center;"| N/A
|}
|}


[[Index Of]] in SHARP APL was not extended to apply to left argument [[major cell]]s as in J and Dyalog; instead it was given rank <source lang=apl inline>1 0</source> making such a change impossible. In A+ not only [[Index Of]] but also [[Membership]] was changed to follow the leading axis model, breaking compatibility with other APLs. A+ also restricts [[Take]] and [[Drop]] to allow only a [[singleton]] left argument (but any right argument rank is permitted). The leading-axis extension of scalar dyadics in SHARP is a direct consequence of giving them a function rank 0, as SHARP's concept of function rank includes [[prefix agreement]].
[[Index Of]] in SHARP APL was not extended to apply to left argument [[major cell]]s as in J and Dyalog; instead it was given rank <syntaxhighlight lang=apl inline>1 0</syntaxhighlight> making such a change impossible. In A+ not only [[Index Of]] but also [[Membership]] was changed to follow the leading axis model, breaking compatibility with other APLs. A+ also restricts [[Take]] and [[Drop]] to allow only a [[singleton]] left argument (but any right argument rank is permitted).


== History ==
== History ==


Leading axis theory was first developed by employees of [[I. P. Sharp Associates]] including [[Ken Iverson]], [[Arthur Whitney]], and [[Bob Bernecky]] in the early 1980s: the [[Rank operator]] itself is attributed to Whitney, who invented it while travelling to the [[APL82]] conference. It was further developed by Iverson and [[Roger Hui]] when creating the [[J]] language in the 1990s and 2000s; the leading axis model and its various incompatibilities with APL had been a major reason to break with APL and create a new language.
Leading axis theory was first developed by employees of [[I. P. Sharp Associates]] including [[Ken Iverson]], [[Arthur Whitney]], and [[Bob Bernecky]] in the early 1980s: the [[Rank operator]] itself is attributed to Whitney, who invented it while travelling to the [[APL82]] conference.<ref>[[Roger Hui]] and [[Morten Kromberg]]. [https://dl.acm.org/doi/abs/10.1145/3386319 ''APL since 1978'']. ACM [[HOPL]] IV. 2020-06.</ref> It was further developed by Iverson and [[Roger Hui]] when creating the [[J]] language in the 1990s and 2000s; the leading axis model and its various incompatibilities with APL had been a major reason to break with APL and create a new language.


Leading axis theory was brought to [[Nested array theory|nested]] APLs by [[Dyalog APL]] in the 2010s after [[Dyalog Ltd.]] employed Hui. Working with [[Jay Foad]] and [[Morten Kromberg]], Hui designed and implemented versions of Rank and other J functionality compatible with Dyalog's nested arrays.
Leading axis theory was brought to [[Nested array theory|nested]] APLs by [[Dyalog APL]] in the 2010s after [[Dyalog Ltd.]] employed Hui. Working with [[Jay Foad]] and [[Morten Kromberg]], Hui designed and implemented versions of Rank and other J functionality compatible with Dyalog's nested arrays.


{{APL features}}
== References ==
<references />
 
{{APL features}}[[Category:Leading axis theory| ]]

Navigation menu