Index Generator

From APL Wiki
Jump to navigation Jump to search
This page is about generating indices for an array of a given size. See Indexing, Indices, Index of, and Interval Index for other operations named after indices.

Index Generator () or Interval, often called by the name of its glyph Iota, is a monadic primitive function which returns an array of indices with shape given by the right argument. In the result, the element at each index is that index.

In all APLs, ⍳l for a scalar l returns a vector of length l counting from the index origin up. Most modern (nested) APLs also define the result for a vector of length r≠1 to be a rank-r array of vector indices; a singleton vector is usually treated as a scalar. J's primitive, called Integers, instead returns a flat numeric array of indices into its own ravel.

Examples

⍳n returns the first n indices in order:

      ⍳ 5
1 2 3 4 5

This result depends on index origin: if the index origin is set to zero, it starts counting from zero instead:

      ⎕IO ← 0
      ⍳ 5
0 1 2 3 4

An argument of 0 produces the empty vector, Zilde:

      ⍳ 0

      ⍬ ≡ ⍳ 0
1

Vector arguments

In A+ and J, Iota always returns a simple array. The equivalence ⍳V V⍴⍳×/V defines the result for non-singleton vectors. If the argument is an empty vector, the result is a scalar: the index origin (which is always 0 in these languages).

   ⍳ 2 3 4
 0  1  2  3
 4  5  6  7
 8  9 10 11

12 13 14 15
16 17 18 19
20 21 22 23
   ⍳ 0⍴0
0
Works in: A+

We might call such a function a "ravel index generator" since the result is an array of scalar indices into its own ravel. In contrast, nested APLs, if they implement Iota for a vector argument (APL2 and APLX, for example, do not), use indices of elements:

      ⍳ 2 5
┌───┬───┬───┬───┬───┐
│1 1│1 2│1 3│1 4│1 5│
├───┼───┼───┼───┼───┤
│2 1│2 2│2 3│2 4│2 5│
└───┴───┴───┴───┴───┘
      ⍳⍬
┌┐
││
└┘
      (⊂⍬) ≡ ⍳⍬
1

The result of ⍳⍬ should have shape , implying it is a scalar, and its only element must be the only possible index into a scalar, the empty vector. This means it must be ⊂⍬. However, Dyalog APL returned the scalar ⎕IO instead prior to version 13.0.

Negative arguments

Two languages extend Iota to allow negative arguments. In both cases, the shape of the result is the absolute value of the argument.

In the nested APL NARS2000, negating one number in the argument subtracts that value from each index along the corresponding axis.

      ⍳2 ¯3
 1 ¯2  1 ¯1  1 0
 2 ¯2  2 ¯1  2 0
Works in: NARS2000, ⎕FEATURE[⎕IO]←1

In J, a negative number reverses the result along that axis.

   i. 2 _3
2 1 0
5 4 3
Works in: J

Scalar-vector discrepancy

In NARS and later nested APLs which share its definition, the result of Iota is simple when the argument is a singleton and nested otherwise. This is because, when the argument is a singleton, each index in the result is represented as a scalar rather than a 1-element vector. dzaima/APL and Kap break from this definition by using vector indices whenever the argument is a vector, and scalar indices if the argument is a scalar, so that the result is only simple if the argument was scalar. This definition has the property that the shape of each index matches the shape of the argument.

Such an extension breaks compatibility with earlier non-nested APLs: although these APLs required the argument of Iota to be a singleton, they always allowed a scalar or vector, and sometimes any singleton. This is because a shape to be passed to Iota would often naturally be a vector: for example, Shape always returns a vector, and a function such as Tally to return a scalar length did not exist.

NARS defines its extension using the equivalence ⍳R ⊃∘.,/⍳¨R based on an Outer Product reduction. For a singleton vector R, this does yield a simple result, because ∘.,/ leaves a singleton argument unchanged. However, this is arguably due to inconsistent design in Reduce: NARS's creator, Bob Smith, argues that Catenate reduction should yield a DOMAIN ERROR, and the same arguments apply to its Outer Product.[1]

History

The Greek letter iota, corresponding to the Latin letter i, now usually treated as a mnemonic for "integers" or "index", more likely stood for "identity" in early Iverson notation. Iverson's 1960 paper The Description of Finite Sequential Processes states that "the identity permutation vector is defined by the relation ."[2] Since is a more typical letter to use for the identity permutation, it's possible that Iverson's choice was also motivated by the convention of using for an inclusion map, where iota now indicates "inclusion" or "injection".[3] The term "inclusion" typically indicates that a particular injection is meant to be treated as an identity.

The notation , "Interval", was used in A Programming Language for the vector of the first indices starting at index origin . Both arguments were optional, with being implied by conformability if omitted. When implemented in APL\360, it took length as the only argument, but allowed it to be a singleton so that expressions like ⍳⍴V would work (Tally had not yet been defined). NARS was the first nested APL to make the extension to a vector argument. This definition has been widely but not universally adopted, with APL2, APLX, or the standard ISO/IEC 13751:2001 choosing not to make any extension. Similar extensions to vectors also appear in BQN and Uiua.

The nested definition used in NARS had been proposed in 1971 by Jim Brown,[4] who noted its similarity to a flat array function Phil Abrams had called "odometer" in a thesis published the year before.[5] The same definition was included in a 1973 research paper by Ghandour and Mezei of IBM.[6] Abrams's flat odometer function is still sometimes used, as in this essay in J. Some K dialects (and derivatives such as Goal) define odometer to be the behavior of ! on a list of integers; this definition flips the axes relative to Abrams's version.

Flat array languages may extend to multiple argument elements in different ways. A Dictionary of APL defines Iota to have function rank 0, and SHARP APL gives it rank 1 but requires each row (1-cell) of the argument to have length 1. In A+ and J, Iota of a vector returns an array which counts up in ravel order, that is, it matches Iota of its bound, reshaped. A+ refers to this function as "Interval" while J calls it "Integers". The same behavior is available in Uiua as un-shape.

Outside of APL

The name "iota" has sometimes been used to indicate an increasing sequence of integers even in languages other than APL. In the C++11 standard library, std::iota() fills an iterator with such a sequence, and was named after the APL glyph.[7][3][8] The Go language also uses the name iota as a predeclared identifier which represents increasing integers: each time it is used within a single constant declaration its value will be one higher.[9] Functions named "iota" appear in libraries such as Scheme's SRFI 1 (list library),[10] GPGPU library ArrayFire,[11] and JavaScript library scijs.[12] The BSD operating system (including derivative macOS) uses jot to print sequential data, a name derived in part from APL's glyph.[13]

See also

External links

Tutorials

Documentation

References

  1. Smith, Bob. "Reduction of Singletons". Minnowbrook 2010.
  2. Ken Iverson. The Description of Finite Sequential Processes. Proceedings of a Conference on Information Theory, C. Cherry and W. Jackson, Editors, Imperial College, London, 1960-08-29.
  3. 3.0 3.1 Sean Parent. "#iotashaming". sean-parent.stlab.cc. 2019-01-04.
  4. Jim Brown. "A Generalization of APL". 1971.
  5. Phil Abrams. An APL Machine. SLAC. 1970-02. Appendix B, p. 143.
  6. Ziad Ghandour and Jorge Mezei. "General Arrays, Operators, and Functions". IBM Journal of Research and Development, volume 17, issue 4. 1973-07.
  7. cppreference.com. std::iota. Retrieved 2020-04-28.
  8. Rob Mayoff. Answer to "What does iota of std::iota stand for?" on Stack Overflow. Retrieved 2020-04-28.
  9. The Go Programming Language Specification. Iota. 2020-01-14.
  10. Olin Shivers. SRFI 1: List Library. Finalized 1999-10-09.
  11. ArrayFire: Functions. iota. Jun 2, 2015.
  12. scijs.not. iota-array. Retrieved 20223-05-11
  13. openbsd.org. jot. Retrieved 2022-08-04.
APL built-ins [edit]
Primitives (Timeline) Functions
Scalar
Monadic ConjugateNegateSignumReciprocalMagnitudeExponentialNatural LogarithmFloorCeilingFactorialNotPi TimesRollTypeImaginarySquare RootRound
Dyadic AddSubtractTimesDivideResiduePowerLogarithmMinimumMaximumBinomialComparison functionsBoolean functions (And, Or, Nand, Nor) ∙ GCDLCMCircularComplexRoot
Non-Scalar
Structural ShapeReshapeTallyDepthRavelEnlistTableCatenateReverseRotateTransposeRazeMixSplitEncloseNestCut (K)PairLinkPartitioned EnclosePartition
Selection FirstPickTakeDropUniqueIdentityStopSelectReplicateExpandSet functions (IntersectionUnionWithout) ∙ Bracket indexingIndexCartesian ProductSort
Selector Index generatorGradeIndex OfInterval IndexIndicesDealPrefix and suffix vectors
Computational MatchNot MatchMembershipFindNub SieveEncodeDecodeMatrix InverseMatrix DivideFormatExecuteMaterialiseRangeCount In
Operators Monadic EachCommuteConstantReplicateExpandReduceWindowed ReduceScanOuter ProductKeyI-BeamSpawnFunction axisIdentity (Null, Ident)
Dyadic BindCompositions (Compose, Reverse Compose, Beside, Withe, Atop, Over) ∙ Inner ProductDeterminantPowerAtUnderRankDepthVariantStencilCutDirect definition (operator)Identity (Lev, Dex)
Quad names Index originComparison toleranceMigration levelAtomic vector