Index Generator: Difference between revisions

Jump to navigation Jump to search
m (Text replacement - "</source>" to "</syntaxhighlight>")
Line 2: Line 2:
{{Built-in|Index Generator|⍳}} or '''Interval''', often called by the name of its [[glyph]] '''Iota''', is a [[monadic]] [[primitive function]] which returns an array of [[index|indices]] with [[shape]] given by the right [[argument]]. In the result, the [[element]] at each [[index]] is that index.
{{Built-in|Index Generator|⍳}} or '''Interval''', often called by the name of its [[glyph]] '''Iota''', is a [[monadic]] [[primitive function]] which returns an array of [[index|indices]] with [[shape]] given by the right [[argument]]. In the result, the [[element]] at each [[index]] is that index.


Originally, Iota was defined only on a single number. In [[APL/360]], and all later APLs, <source lang=apl inline>⍳l</source> for a [[scalar]] <source lang=apl inline>l</source> returns a [[simple]] [[numeric]] [[vector]] of length <source lang=apl inline>l</source> counting from the [[index origin]] up. In [[Nested array theory|nested]] APLs, this result may be seen as an array of [[scalar]] indices; [[NARS]] extended Iota to allow a vector argument by making the result for a non-[[singleton]] vector be an array of vector indices. [[Flat array theory|Flat]] APLs do not use this extension, but 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]], [[reshape]]d. A+ refers to this function as '''Interval''' while J calls it '''Integers'''.
Originally, Iota was defined only on a single number. In [[APL/360]], and all later APLs, <source lang=apl inline>⍳l</syntaxhighlight> for a [[scalar]] <source lang=apl inline>l</syntaxhighlight> returns a [[simple]] [[numeric]] [[vector]] of length <source lang=apl inline>l</syntaxhighlight> counting from the [[index origin]] up. In [[Nested array theory|nested]] APLs, this result may be seen as an array of [[scalar]] indices; [[NARS]] extended Iota to allow a vector argument by making the result for a non-[[singleton]] vector be an array of vector indices. [[Flat array theory|Flat]] APLs do not use this extension, but 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]], [[reshape]]d. A+ refers to this function as '''Interval''' while J calls it '''Integers'''.


== Examples ==
== Examples ==


<source lang=apl inline>⍳n</source> returns the first <source lang=apl inline>n</source> [[index|indices]] in order:
<source lang=apl inline>⍳n</syntaxhighlight> returns the first <source lang=apl inline>n</syntaxhighlight> [[index|indices]] in order:
<source lang=apl>
<source lang=apl>
       ⍳ 5
       ⍳ 5
1 2 3 4 5
1 2 3 4 5
</source>
</syntaxhighlight>
This result depends on [[index origin]]: if the index origin is set to zero, it starts counting from zero instead:
This result depends on [[index origin]]: if the index origin is set to zero, it starts counting from zero instead:
<source lang=apl>
<source lang=apl>
Line 16: Line 16:
       ⍳ 5
       ⍳ 5
0 1 2 3 4
0 1 2 3 4
</source>
</syntaxhighlight>
An argument of <source lang=apl inline>0</source> produces the [[empty]] [[vector]], [[Zilde]]:
An argument of <source lang=apl inline>0</syntaxhighlight> produces the [[empty]] [[vector]], [[Zilde]]:
<source lang=apl>
<source lang=apl>
       ⍳ 0
       ⍳ 0
Line 23: Line 23:
       ⍬ ≡ ⍳ 0
       ⍬ ≡ ⍳ 0
1
1
</source>
</syntaxhighlight>


=== Vector arguments ===
=== Vector arguments ===


In [[A+]] and [[J]], Iota always returns a [[simple]] array. The equivalence <source lang=apl inline>⍳V</source> {{←→}} <source lang=apl inline>V⍴⍳×/V</source> 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).
In [[A+]] and [[J]], Iota always returns a [[simple]] array. The equivalence <source lang=apl inline>⍳V</syntaxhighlight> {{←→}} <source lang=apl inline>V⍴⍳×/V</syntaxhighlight> 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).
<source lang=apl>
<source lang=apl>
   ⍳ 2 3 4
   ⍳ 2 3 4
Line 39: Line 39:
   ⍳ 0⍴0
   ⍳ 0⍴0
0
0
</source>{{Works in|[[A+]]}}
</syntaxhighlight>{{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 array theory|nested]] APLs, if they implement Iota for a vector argument ([[APL2]] and [[APLX]], for example, do not), use [[index|indices]] of [[element]]s:
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 array theory|nested]] APLs, if they implement Iota for a vector argument ([[APL2]] and [[APLX]], for example, do not), use [[index|indices]] of [[element]]s:
<source lang=apl>
<source lang=apl>
Line 54: Line 54:
       (⊂⍬) ≡ ⍳⍬
       (⊂⍬) ≡ ⍳⍬
1
1
</source>{{Works in|[[NARS]], [[NARS2000]], [[Dyalog APL]], [[GNU APL]], [[ngn/apl]], [[dzaima/APL]]}}
</syntaxhighlight>{{Works in|[[NARS]], [[NARS2000]], [[Dyalog APL]], [[GNU APL]], [[ngn/apl]], [[dzaima/APL]]}}
The result of <source lang=apl inline>⍳⍬</source> should have [[shape]] <source lang=apl inline>⍬</source>, 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 <source lang=apl inline>⊂⍬</source>. However, [[Dyalog APL]] returned the scalar <source lang=apl inline>⎕IO</source> instead prior to [[Dyalog APL 13.0|version 13.0]].
The result of <source lang=apl inline>⍳⍬</syntaxhighlight> should have [[shape]] <source lang=apl inline>⍬</syntaxhighlight>, 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 <source lang=apl inline>⊂⍬</syntaxhighlight>. However, [[Dyalog APL]] returned the scalar <source lang=apl inline>⎕IO</syntaxhighlight> instead prior to [[Dyalog APL 13.0|version 13.0]].


=== Negative arguments ===
=== Negative arguments ===
Line 66: Line 66:
  1 ¯2  1 ¯1  1 0
  1 ¯2  1 ¯1  1 0
  2 ¯2  2 ¯1  2 0
  2 ¯2  2 ¯1  2 0
</source>{{Works in|[[NARS2000]], <source lang=apl inline>⎕FEATURE[⎕IO]←1</source>}}
</syntaxhighlight>{{Works in|[[NARS2000]], <source lang=apl inline>⎕FEATURE[⎕IO]←1</syntaxhighlight>}}


In [[J]], a negative number [[reverse]]s the result along that axis.
In [[J]], a negative number [[reverse]]s the result along that axis.
Line 73: Line 73:
2 1 0
2 1 0
5 4 3
5 4 3
</source>{{Works in|[[J]]}}
</syntaxhighlight>{{Works in|[[J]]}}


== Scalar-vector discrepancy in nested APLs ==
== Scalar-vector discrepancy in nested APLs ==
Line 81: Line 81:
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.
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 <source lang=apl inline>⍳R</source> {{←→}} <source lang=apl inline>⊃∘.,/⍳¨R</source> based on an [[Outer Product]] [[reduction]]. For a singleton vector <source lang=apl inline>R</source>, this does yield a simple result, because <source lang=apl inline>∘.,/</source> 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.<ref>[[Bob Smith|Smith, Bob]]. [http://www.sudleyplace.com/APL/Reduction%20Of%20Singletons.pdf "Reduction of Singletons"]. [[Minnowbrook]] 2010.</ref>
[[NARS]] defines its extension using the equivalence <source lang=apl inline>⍳R</syntaxhighlight> {{←→}} <source lang=apl inline>⊃∘.,/⍳¨R</syntaxhighlight> based on an [[Outer Product]] [[reduction]]. For a singleton vector <source lang=apl inline>R</syntaxhighlight>, this does yield a simple result, because <source lang=apl inline>∘.,/</syntaxhighlight> 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.<ref>[[Bob Smith|Smith, Bob]]. [http://www.sudleyplace.com/APL/Reduction%20Of%20Singletons.pdf "Reduction of Singletons"]. [[Minnowbrook]] 2010.</ref>


== History ==
== History ==
Line 92: Line 92:


The name "iota" has sometimes been used to indicate an increasing sequence of integers even in languages other than APL:
The name "iota" has sometimes been used to indicate an increasing sequence of integers even in languages other than APL:
* The [[wikipedia:C++|C++11]] standard library has <source lang=c++ inline>std::iota()</source> fills an iterator with such a sequence, and was named after the APL glyph.<ref>cppreference.com. [https://en.cppreference.com/w/cpp/algorithm/iota std::iota]. Retrieved 2020-04-28.</ref><ref name="iotashaming"/><ref>Rob Mayoff. [https://stackoverflow.com/a/9244949 Answer to "What does iota of std::iota stand for?"] on Stack Overflow.  Retrieved 2020-04-28.</ref>
* The [[wikipedia:C++|C++11]] standard library has <source lang=c++ inline>std::iota()</syntaxhighlight> fills an iterator with such a sequence, and was named after the APL glyph.<ref>cppreference.com. [https://en.cppreference.com/w/cpp/algorithm/iota std::iota]. Retrieved 2020-04-28.</ref><ref name="iotashaming"/><ref>Rob Mayoff. [https://stackoverflow.com/a/9244949 Answer to "What does iota of std::iota stand for?"] on Stack Overflow.  Retrieved 2020-04-28.</ref>
* The [[wikipedia:Go (programming language)|Go]] language also uses the name <source lang=go inline>iota</source> as a predeclared identifier which represents increasing integers: each time it is used within a single constant declaration its value will be one higher.<ref>The Go Programming Language Specification. [https://golang.org/ref/spec#Iota Iota]. 2020-01-14.</ref>
* The [[wikipedia:Go (programming language)|Go]] language also uses the name <source lang=go inline>iota</syntaxhighlight> as a predeclared identifier which represents increasing integers: each time it is used within a single constant declaration its value will be one higher.<ref>The Go Programming Language Specification. [https://golang.org/ref/spec#Iota Iota]. 2020-01-14.</ref>
* The popular [[wikipedia:Scheme (programming language)|Scheme]] list library SRFI 1 also includes a function called <source lang=scheme inline>iota</source> in reference to APL, which takes a count as well as optional starting value (default 0) and step size (default 1) arguments.<ref>Olin Shivers. [https://srfi.schemers.org/srfi-1/srfi-1.html#iota SRFI 1: List Library]. Finalized 1999-10-09.</ref>
* The popular [[wikipedia:Scheme (programming language)|Scheme]] list library SRFI 1 also includes a function called <source lang=scheme inline>iota</syntaxhighlight> in reference to APL, which takes a count as well as optional starting value (default 0) and step size (default 1) arguments.<ref>Olin Shivers. [https://srfi.schemers.org/srfi-1/srfi-1.html#iota SRFI 1: List Library]. Finalized 1999-10-09.</ref>
* The [[wikipedia:ArrayFire|ArrayFire]] library for [[wikipedia:general-purpose computing on graphics processing units|general-purpose computing on graphics processing units]] has an <source lang=c inline>iota</source> function with a result similar to that of A+ and J when given a [[#Vector_arguments|vector argument]].<ref>ArrayFire: Functions. [https://arrayfire.org/docs/group__data__func__iota.htm iota]. Jun 2, 2015.</ref>
* The [[wikipedia:ArrayFire|ArrayFire]] library for [[wikipedia:general-purpose computing on graphics processing units|general-purpose computing on graphics processing units]] has an <source lang=c inline>iota</syntaxhighlight> function with a result similar to that of A+ and J when given a [[#Vector_arguments|vector argument]].<ref>ArrayFire: Functions. [https://arrayfire.org/docs/group__data__func__iota.htm iota]. Jun 2, 2015.</ref>
* The [[wikipedia:Berkeley Software Distribution|BSD]] operating system and its derivatives, for example [[wikipedia:macOS|macOS]], have a <source lang=shell inline>jot</source> which can print sequential data. The name <source lang=shell inline>jot</source> derives in part from APL's glyph.<ref>openbsd.org. [https://man.openbsd.org/jot#DESCRIPTION jot]. Retrieved 2022-08-04.</ref>
* The [[wikipedia:Berkeley Software Distribution|BSD]] operating system and its derivatives, for example [[wikipedia:macOS|macOS]], have a <source lang=shell inline>jot</syntaxhighlight> which can print sequential data. The name <source lang=shell inline>jot</syntaxhighlight> derives in part from APL's glyph.<ref>openbsd.org. [https://man.openbsd.org/jot#DESCRIPTION jot]. Retrieved 2022-08-04.</ref>


== See also ==
== See also ==