# Difference between revisions of "Scalar extension"

Miraheze>Adám Brudzewsky |
|||

(14 intermediate revisions by 5 users not shown) | |||

Line 1: | Line 1: | ||

− | Scalar extension is a way to apply a function with a [[scalar]] argument when an array of a particular non-empty [[shape]] would be expected. The scalar is ''extended'' to this shape by treating it as an array with each element equal to the scalar's only element. This is equivalent to reshaping the scalar to fit the desired shape. | + | '''Scalar extension''' is a way to apply a [[function]] with a [[scalar]] argument when an array of a particular non-[[empty]] [[shape]] would be expected. The scalar is ''extended'' to this shape by treating it as an array with each [[element]] equal to the scalar's only element. This is equivalent to [[Reshape|reshaping]] the scalar to fit the desired shape. |

== History and terminology == | == History and terminology == | ||

− | The concept of scalar extension has been around since [[APL\360]]. An example which extends the scalar < | + | The concept of scalar extension has been around since [[APL\360]]. An example which extends the scalar <source lang=apl inline>2</source> is: |

− | < | + | <source lang=apl> |

2 × 1 2 3 4 | 2 × 1 2 3 4 | ||

2 4 6 8 | 2 4 6 8 | ||

− | </ | + | </source> |

− | [[A Programming Language]] describes the above computation as a "scalar multiple" but does not generalise it to arbitrary [[scalar | + | [[A Programming Language]] describes the above computation as a "scalar multiple" but does not generalise it to arbitrary [[scalar function]]s, so it's unclear when scalar extension as a unified concept was adopted in [[Iverson notation]]. |

The word "extension" applies to scalar extension in two ways: first, a function is extended by making a case which would have been a [[RANK ERROR]] into a valid application. Second, the application works by conceptually extending the scalar to function as though it were an array of higher rank. | The word "extension" applies to scalar extension in two ways: first, a function is extended by making a case which would have been a [[RANK ERROR]] into a valid application. Second, the application works by conceptually extending the scalar to function as though it were an array of higher rank. | ||

− | Two arrays are said to [[Conformability|conform]] if they have the same shape or at least one can be extended (it is a scalar, or, in langauges with singleton extension, has exactly one element). A pair of conforming arrays defines a single shape which describes how their elements are paired: if neither is a scalar, it is their shared shape; if one is a scalar, it is the other's shape; if both are scalars, it is < | + | Two arrays are said to [[Conformability|conform]] if they have the same shape or at least one can be extended (it is a scalar, or, in langauges with singleton extension, has exactly one element). A pair of conforming arrays defines a single shape which describes how their elements are paired: if neither is a scalar, it is their shared shape; if one is a scalar, it is the other's shape; if both are scalars, it is the [[empty]] vector, <source lang=apl inline>⍬</source> ([[Zilde]]). |

=== Rank extension === | === Rank extension === | ||

− | The term "scalar extension" is sometimes used to refer to the practice of allowing a scalar when a higher rank is expected. The scalar is treated as an array of the expected minimum rank whose shape is a vector of 1s (that is, a [[singleton]]). For example, < | + | The term "scalar extension" is sometimes used to refer to the practice of allowing a scalar when a higher rank is expected. The scalar is treated as an array of the expected minimum rank whose shape is a vector of 1s (that is, a [[singleton]]). For example, <source lang=apl inline>⍳8</source> and <source lang=apl inline>8⍴'a'</source> both produce an 8-element array even though the shape of an array is always a vector and so cannot be equal to <source lang=apl inline>8</source>. This type of extension, which differs from ordinary scalar extension in that there is no expected shape and only an expected rank, has also been present since [[APL\360]]. |

=== Singleton extension === | === Singleton extension === | ||

− | Some APLs, such as [[Dyalog APL]], treat arrays with one element ( | + | Some APLs, such as [[Dyalog APL]], treat arrays with one element ([[singleton]]s) as scalars for the purposes of scalar extension. This practice is referred to as "singleton extension". For example, |

− | < | + | <source lang=apl> |

(1 1⍴5) + 10 20 | (1 1⍴5) + 10 20 | ||

15 25 | 15 25 | ||

⍴ (1 1⍴5) + 10 20 | ⍴ (1 1⍴5) + 10 20 | ||

2 | 2 | ||

− | </ | + | </source> |

{{Works in|[[Dyalog APL]], [[APLX]]}} | {{Works in|[[Dyalog APL]], [[APLX]]}} | ||

In this case addition accepts a singleton, and discards its shape. If two singletons are used as arguments, they are still considered to [[Conformability|conform]]; the shape of the result is taken from the argument with higher rank. | In this case addition accepts a singleton, and discards its shape. If two singletons are used as arguments, they are still considered to [[Conformability|conform]]; the shape of the result is taken from the argument with higher rank. | ||

Line 38: | Line 38: | ||

== Examples == | == Examples == | ||

− | Dyadic [[scalar functions]] and the [[Each | + | Dyadic [[scalar functions]] and the [[Each]] operator use scalar extension to pair their arguments: |

<source lang=apl> | <source lang=apl> | ||

1 2 3 4 * 2 | 1 2 3 4 * 2 | ||

1 4 9 16 | 1 4 9 16 | ||

+ | 100,¨1 2 3 4 | ||

+ | ┌─────┬─────┬─────┬─────┐ | ||

+ | │100 1│100 2│100 3│100 4│ | ||

+ | └─────┴─────┴─────┴─────┘ | ||

</source> | </source> | ||

− | [[Replicate]] and [[ | + | [[Replicate]] and [[Partitioned Enclose]] (and also [[Partition]], but this is less useful, as it is equivalent to <source lang=apl inline>,⊂</source> or <source lang=apl inline>{0⍴⊂0⍴⍵}</source>) extend a scalar left argument to apply to each column of the right argument: |

<source lang=apl> | <source lang=apl> | ||

2/'abc' | 2/'abc' | ||

aabbcc | aabbcc | ||

+ | 2⊂'abc' | ||

+ | ┌┬─┬┬─┬┬─┐ | ||

+ | ││a││b││c│ | ||

+ | └┴─┴┴─┴┴─┘ | ||

+ | </source> | ||

+ | |||

+ | [[Decode]] uses extends a single radix left argument to apply to all digit values in the right argument: | ||

+ | <source lang=apl> | ||

+ | 2⊥1 0 1 | ||

+ | 5 | ||

</source> | </source> | ||

+ | |||

[[APL2]] and [[Dyalog APL]] use a variant of singleton extension when the selected axis of the right argument has length one: each element along that axis is reused for every element of the left argument. | [[APL2]] and [[Dyalog APL]] use a variant of singleton extension when the selected axis of the right argument has length one: each element along that axis is reused for every element of the left argument. | ||

<source lang=apl> | <source lang=apl> | ||

Line 55: | Line 70: | ||

7 5 8 | 7 5 8 | ||

</source> | </source> | ||

− | {{Works in|[[Dyalog APL]], [APL2], [APLX]}} | + | {{Works in|[[Dyalog APL]], [[APL2]], [[APLX]]}} |

Line 64: | Line 79: | ||

larsca | larsca | ||

</source> | </source> | ||

+ | |||

+ | === Each left and each right === | ||

+ | |||

+ | A common problem is pairing up each [[element]] of one [[argument]] with all the elements of another argument. Because of scalar extension, [[enclose|making one argument a scalar]] accomplishes this: | ||

+ | <source lang=apl> | ||

+ | 1 2 3,¨⊂100 200 | ||

+ | ┌─────────┬─────────┬─────────┐ | ||

+ | │1 100 200│2 100 200│3 100 200│ | ||

+ | └─────────┴─────────┴─────────┘ | ||

+ | (⊂1 2 3),¨100 200 | ||

+ | ┌─────────┬─────────┐ | ||

+ | │1 2 3 100│1 2 3 200│ | ||

+ | └─────────┴─────────┘ | ||

+ | </source> | ||

+ | For [[scalar function]]s, explicit use of the [[Each]] operator is unnecessary: | ||

+ | <source lang=apl> | ||

+ | 1 2 3+⊂100 200 | ||

+ | ┌───────┬───────┬───────┐ | ||

+ | │101 201│102 202│103 203│ | ||

+ | └───────┴───────┴───────┘ | ||

+ | (⊂1 2 3)+100 200 | ||

+ | ┌───────────┬───────────┐ | ||

+ | │101 102 103│201 202 203│ | ||

+ | └───────────┴───────────┘ | ||

+ | </source> | ||

+ | [[Bind]]ing one argument to the function also works, but this always requires the Each operator: | ||

+ | <source lang=apl> | ||

+ | 1 2 3∘,¨100 200 | ||

+ | ┌─────────┬─────────┐ | ||

+ | │1 2 3 100│1 2 3 200│ | ||

+ | └─────────┴─────────┘ | ||

+ | (,∘100 200)¨1 2 3 | ||

+ | ┌─────────┬─────────┬─────────┐ | ||

+ | │1 100 200│2 100 200│3 100 200│ | ||

+ | └─────────┴─────────┴─────────┘ | ||

+ | </source> | ||

+ | {{APL features}}[[Category:Function characteristics]][[Category:Conformability]] |

## Latest revision as of 09:54, 8 July 2021

**Scalar extension** is a way to apply a function with a scalar argument when an array of a particular non-empty shape would be expected. The scalar is *extended* to this shape by treating it as an array with each element equal to the scalar's only element. This is equivalent to reshaping the scalar to fit the desired shape.

## Contents

## History and terminology

The concept of scalar extension has been around since APL\360. An example which extends the scalar `2`

is:

```
2 × 1 2 3 4
2 4 6 8
```

A Programming Language describes the above computation as a "scalar multiple" but does not generalise it to arbitrary scalar functions, so it's unclear when scalar extension as a unified concept was adopted in Iverson notation.

The word "extension" applies to scalar extension in two ways: first, a function is extended by making a case which would have been a RANK ERROR into a valid application. Second, the application works by conceptually extending the scalar to function as though it were an array of higher rank.

Two arrays are said to conform if they have the same shape or at least one can be extended (it is a scalar, or, in langauges with singleton extension, has exactly one element). A pair of conforming arrays defines a single shape which describes how their elements are paired: if neither is a scalar, it is their shared shape; if one is a scalar, it is the other's shape; if both are scalars, it is the empty vector, `⍬`

(Zilde).

### Rank extension

The term "scalar extension" is sometimes used to refer to the practice of allowing a scalar when a higher rank is expected. The scalar is treated as an array of the expected minimum rank whose shape is a vector of 1s (that is, a singleton). For example, `⍳8`

and `8⍴'a'`

both produce an 8-element array even though the shape of an array is always a vector and so cannot be equal to `8`

. This type of extension, which differs from ordinary scalar extension in that there is no expected shape and only an expected rank, has also been present since APL\360.

### Singleton extension

Some APLs, such as Dyalog APL, treat arrays with one element (singletons) as scalars for the purposes of scalar extension. This practice is referred to as "singleton extension". For example,

```
(1 1⍴5) + 10 20
15 25
⍴ (1 1⍴5) + 10 20
2
```

In this case addition accepts a singleton, and discards its shape. If two singletons are used as arguments, they are still considered to conform; the shape of the result is taken from the argument with higher rank.

Singleton extension can sometimes conflict with other extensions, an issue which does not occur with scalar extension. If a function is extended to allow a shorter vector argument to be extended (perhaps by padding with 0), but it also supports singleton extension, then there is a conflict with length-1 vectors.

## Extension in the Rank operator

The Rank operator uses a generalization of scalar extension to pair cells. A function called with rank 0 exhibits ordinary scalar extension: it acts like a scalar function. A function with higher rank extends not scalars (arrays with empty shape) but arrays whose frame is empty. An empty frame implies there is only one cell, and it has a scalar-like array structure. This cell can be extended by reusing it for every function call.

## Examples

Dyadic scalar functions and the Each operator use scalar extension to pair their arguments:

```
1 2 3 4 * 2
1 4 9 16
100,¨1 2 3 4
┌─────┬─────┬─────┬─────┐
│100 1│100 2│100 3│100 4│
└─────┴─────┴─────┴─────┘
```

Replicate and Partitioned Enclose (and also Partition, but this is less useful, as it is equivalent to `,⊂`

or `{0⍴⊂0⍴⍵}`

) extend a scalar left argument to apply to each column of the right argument:

```
2/'abc'
aabbcc
2⊂'abc'
┌┬─┬┬─┬┬─┐
││a││b││c│
└┴─┴┴─┴┴─┘
```

Decode uses extends a single radix left argument to apply to all digit values in the right argument:

```
2⊥1 0 1
5
```

APL2 and Dyalog APL use a variant of singleton extension when the selected axis of the right argument has length one: each element along that axis is reused for every element of the left argument.

```
⍴ 2 ¯3 /[2] 7 1 8⍴⍳56
7 5 8
```

In languages which allow a vector left argument to Rotate, the behavior with a scalar left argument follows from scalar extension. In the following example a length-2 vector could be used to rotate each row by a different amount. A scalar rotates both rows by the same amount.

```
3⌽2 6⍴'extendscalar'
endext
larsca
```

### Each left and each right

A common problem is pairing up each element of one argument with all the elements of another argument. Because of scalar extension, making one argument a scalar accomplishes this:

```
1 2 3,¨⊂100 200
┌─────────┬─────────┬─────────┐
│1 100 200│2 100 200│3 100 200│
└─────────┴─────────┴─────────┘
(⊂1 2 3),¨100 200
┌─────────┬─────────┐
│1 2 3 100│1 2 3 200│
└─────────┴─────────┘
```

For scalar functions, explicit use of the Each operator is unnecessary:

```
1 2 3+⊂100 200
┌───────┬───────┬───────┐
│101 201│102 202│103 203│
└───────┴───────┴───────┘
(⊂1 2 3)+100 200
┌───────────┬───────────┐
│101 102 103│201 202 203│
└───────────┴───────────┘
```

Binding one argument to the function also works, but this always requires the Each operator:

```
1 2 3∘,¨100 200
┌─────────┬─────────┐
│1 2 3 100│1 2 3 200│
└─────────┴─────────┘
(,∘100 200)¨1 2 3
┌─────────┬─────────┬─────────┐
│1 100 200│2 100 200│3 100 200│
└─────────┴─────────┴─────────┘
```

APL features [edit]
| |
---|---|

Built-ins | Primitives (functions, operators) ∙ Quad name |

Array model | Shape ∙ Rank ∙ Depth ∙ Bound ∙ Index (Indexing) ∙ Axis ∙ Ravel ∙ Ravel order ∙ Element ∙ Scalar ∙ Vector ∙ Matrix ∙ Simple scalar ∙ Simple array ∙ Nested array ∙ Cell ∙ Major cell ∙ Subarray ∙ Empty array ∙ Prototype |

Data types | Number (Boolean, Complex number) ∙ Character (String) ∙ Box ∙ Namespace |

Concepts and paradigms | Leading axis theory ∙ Scalar extension ∙ Conformability ∙ Leading axis agreement ∙ Scalar function ∙ Pervasion ∙ Glyph ∙ Identity element ∙ Complex floor ∙ Total array ordering |

Errors | LIMIT ERROR ∙ RANK ERROR ∙ SYNTAX ERROR ∙ DOMAIN ERROR ∙ LENGTH ERROR ∙ INDEX ERROR ∙ VALUE ERROR |