Take: Difference between revisions
Miraheze>Marshall |
Miraheze>Marshall (→History: APL\360 history) |
||
Line 97: | Line 97: | ||
== History == | == History == | ||
In [[A Programming Language]], prefix and suffix operations were described using the syntax <code>⍺<sup>j</sup>/x</code> to take the first <code>j</code> elements of vector <code>x</code> and <code>⍵<sup>j</sup>/x</code> for the last <code>j</code> elements. This combined a use of the special prefix and suffix vectors <code>⍺<sup>j</sup>(n)</code> and <code>⍵<sup>j</sup>(n)</code> with [[Compress|compression]], with the length <code>n</code> inferred based on the length of <code>x</code>. The symbol <code>↑</code> was used for vector [[Rotate]], while <code>↓</code> rotated in the opposite direction.<ref>Iverson, | In [[A Programming Language]], prefix and suffix operations were described using the syntax <code>⍺<sup>j</sup>/x</code> to take the first <code>j</code> elements of vector <code>x</code> and <code>⍵<sup>j</sup>/x</code> for the last <code>j</code> elements. This combined a use of the special prefix and suffix vectors <code>⍺<sup>j</sup>(n)</code> and <code>⍵<sup>j</sup>(n)</code> with [[Compress|compression]], with the length <code>n</code> inferred based on the length of <code>x</code>. The symbol <code>↑</code> was used for vector [[Rotate]], while <code>↓</code> rotated in the opposite direction.<ref>Iverson, K.E. (1962). A Programming Language. Wiley. ISBN 978-0-471-43014-8.</ref> | ||
Take using the symbol <code>↑</code> was first | Take using the symbol <code>↑</code> was absent from the first version of [[APL\360]]<ref>Falkoff, A.D., and K.E. Iverson. [https://www.jsoftware.com/papers/APL360TerminalSystem.htm "The APL\360 Terminal System"]. Research Report RC-1922, IBM, 1967-10-16.</ref> but was introduced by 1968<ref>Falkoff, A.D., and K.E. Iverson, "[http://keiapl.org/archive/APL360_UsersMan_Aug1968.pdf APL\360 User's Manual]". IBM, August 1968.</ref>. | ||
The [[Function axis|axis]] specification for Take was defined in [[APL2]]. It is shared by [[SHARP APL]] and [[Rationalized APL]], and continues to be supported in [[Dyalog APL]]. | The [[Function axis|axis]] specification for Take was defined in [[APL2]]. It is shared by [[SHARP APL]] and [[Rationalized APL]], and continues to be supported in [[Dyalog APL]]. |
Revision as of 14:17, 18 October 2019
Take (↑
) is a primitive function which shortens or extends an array along one or more axes. The vector left argument indicates the lengths of result axes, with a sign to denote whether elements should be taken starting from the beginning or end of each axis. Take was introduced in APL\360 with the requirement that the left argument length match the right argument rank, and was extended in SHARP APL 19.0 to allow short left arguments. It is closely related to Drop, which removes the parts of each axis that Take would include.
Examples
Take may be used to get the first few, or last few, elements of a vector:
3 ↑ 5 4 3 2 1 5 4 3 ¯3 ↑ 5 4 3 2 1 3 2 1
The left argument to length specifies a length, and not an index. It does not depend on index origin.
A length which is larger than the argument length causes fills to be inserted. The alignment remains the same: if two different positive arguments are used to take from an array, the one which is closer to zero gives a prefix of the other result. If they are both negative, it is a suffix instead. When Take makes an axis longer, it is said to "overtake" along that axis.
8 ↑ 5 4 3 2 1 5 4 3 2 1 0 0 0 ¯8 ↑ 5 4 3 2 1 0 0 0 5 4 3 2 1
A higher-rank array can be shortened by using a left argument with one element for each axis:
¯2 3↑⍳4 5 ┌───┬───┬───┐ │3 1│3 2│3 3│ ├───┼───┼───┤ │4 1│4 2│4 3│ └───┴───┴───┘
In languages with the SHARP APL extension, the left argument can be shortened. This causes leading axes of the right argument to be modified while trailing axes are ignored.
¯2↑⍳4 5 ┌───┬───┬───┬───┬───┐ │3 1│3 2│3 3│3 4│3 5│ ├───┼───┼───┼───┼───┤ │4 1│4 2│4 3│4 4│4 5│ └───┴───┴───┴───┴───┘
An axis may be specified to apply left argument elements to specific axes of the right argument. Here the last axis is specified in order to take two columns of the argument.
¯2↑[2]⍳4 5 ┌───┬───┐ │1 4│1 5│ ├───┼───┤ │2 4│2 5│ ├───┼───┤ │3 4│3 5│ ├───┼───┤ │4 4│4 5│ └───┴───┘
If the Rank operator is available then ¯2↑⍤1⍳4 5
is an equivalent expression.
Description
In the expression X↑Y
, X
may be any array, and Y
is a simple numeric vector whose length is less than or equal to the rank of Y
. Many APLs require the length to be exactly equal; however, an extension by SHARP APL to allow a shorter left argument has been widely adopted by recent APLs. X
may also be a scalar, in which case it is treated as a one-element vector in an instance of scalar rank extension. In some APLs, Y
is also subject to scalar rank extension: if it is scalar then it will be extended so its rank is the length ≢X
.
Elements of X
are matched with axes of Y
with the same index, that is, the left argument corresponds to leading axes of the right. The trailing axes of Y
which are not matched in this way are unchanged by Take; this may also be modelled by extending X
using the lengths of those axes.
For each modified axis the result length along that axis is equal to the corresponding element of |X
. If the original element in X
is positive then the result is aligned with the argument at the beginning of that axis, and if that element is negative they are aligned at the end. If it is zero then the result is empty, so both are true. Elements from the right argument are used in the result until the result is filled. If the argument axis is shorter than the result axis then fills are used once it is exhausted. If the result is empty, its prototype is the same as the right argument's.
If the result is no larger than the right argument along each axis (equivalently, no fills are used, or (|X)≤(≢X)↑⍴Y
), then the result is a subarray of Y
. Not all subarrays can be produced in this way: only those which align with one boundary of the argument along each axis.
Axis specification
When Take is called with axis, the axis determines how elements of the left argument correspond to axes of the right argument. The left argument and axis are required to have rank no more than 1 and are treated as vectors. Their lengths must match, and be less than or equal to the rank of the right argument. Then each element of the left argument applies to the right argument axis given by the corresponding element of the axis vector. Each axis may only be specified once, and unspecified axes are left unchanged.
APL model
The following dfn models Take as defined by Dyalog APL but with no axis specification or error checking. It is implemented by construction a nested array of indices and using these to select from the right argument, with prototypes used for out-of-range indices. It explicitly includes scalar rank extension for the right argument and the SHARP APL extension; if these extensions are not wanted those lines can be removed. Scalar rank extension of the left argument is inherited from Iota and scalar function extension.
Take ← { ⎕IO←0 ⍝ For index comparisons r s ← ≢¨(⍴⍵)(⍺) ⍝ Rank and number of modified axes (r=0)∧s>0: ⍺∇(s⍴1)⍴⍵ ⍝ Right argument scalar rank extension s<r: (⍺,(s-r)∇⍴⍵)∇⍵ ⍝ SHARP APL extension inds ← ((⍺<0)×⍺+⍴⍵)∘+¨ ⍳|⍺ ⍝ Indices to select sel ← { ∧/(0≤⍺)∧⍺<⍴⍵: (⊂⍺)⊃⍵ ⍝ In range: use Pick ⊃0⍴⍵ ⍝ Otherwise, get prototype } sel∘⍵¨ inds }
This definition could be converted to work in a flat APL with the Rank operator by using an odometer function like ⊢⊤(⍳×/)
in place of Iota and changing the two subsequent uses of Each to Rank 1.
History
In A Programming Language, prefix and suffix operations were described using the syntax ⍺j/x
to take the first j
elements of vector x
and ⍵j/x
for the last j
elements. This combined a use of the special prefix and suffix vectors ⍺j(n)
and ⍵j(n)
with compression, with the length n
inferred based on the length of x
. The symbol ↑
was used for vector Rotate, while ↓
rotated in the opposite direction.[1]
Take using the symbol ↑
was absent from the first version of APL\360[2] but was introduced by 1968[3].
The axis specification for Take was defined in APL2. It is shared by SHARP APL and Rationalized APL, and continues to be supported in Dyalog APL.
SHARP APL 19.0, released in 1987, extended Take to allow short left arguments. The choice to align left argument elements with the leading axes of the right argument was made according to the nascent leading axis theory: while a user may not have any preference for manipulating the earlier dimensions, this choice makes Take more flexible when used with the Rank operator.[4] This extension is also used in Dyalog APL, J, and ngn/APL. It was not adopted in ISO/IEC 13751:2001.
Extension support
Language | Scalar right arg | Short left arg | Axis specification |
---|---|---|---|
APL\360 | N | N | N |
APL2 | Y | N | Y |
SHARP APL | Y | Y | Y |
Dyalog APL | Y | Y | Y |
J ({. ) |
Y | Y | N |
GNU APL | Y | N | Y |
ngn/apl | Y | Y | N |
dzaima/APL | N | Y | N |
Documentation
J dictionary, NuVoc
Other resources
References
- ↑ Iverson, K.E. (1962). A Programming Language. Wiley. ISBN 978-0-471-43014-8.
- ↑ Falkoff, A.D., and K.E. Iverson. "The APL\360 Terminal System". Research Report RC-1922, IBM, 1967-10-16.
- ↑ Falkoff, A.D., and K.E. Iverson, "APL\360 User's Manual". IBM, August 1968.
- ↑ Bernecky, Robert. "An Introduction to Function Rank". APL88 Conference Proceedings. ACM SIGAPL Quote Quad, 18(2), December 1987.