rslt ← {⍺←⊢} (new ##.at sel) old            ⍝ Prefix-friendly @.

[new] items replace [sel]ected items of [old] to produce [rslt].

Suggested by Aaron Hsu and Roger Hui, this model  extends  Dyalog's  primitive @
operator with "prefix agreement" for both right-operand [sel]ection and left op-
erand [new] values. In this model:

the shape of a boolean selection mask can be any prefix of the shape of [old]:
    ¯¯¯¯¯                                                      ¯¯¯¯¯
        lcase at{1 0 1} 3 4⍴⎕A      ⍝ vector (1 0 1) selection of matrix rows
    abcd                              ¯¯¯¯¯¯         ¯¯¯¯¯¯¯¯¯    ¯¯¯¯¯¯
    EFGH
    ijkl

the shape of the [new] values can be any prefix of the shape of the selection:
    ¯¯¯¯¯                                              ¯¯¯¯¯
        'XY'at 1 3 ⊢3 4⍴'*'         ⍝ vector 'XY' substitution of matrix rows
    XXXX                              ¯¯¯¯¯¯      ¯¯¯¯¯¯¯¯¯¯¯¯    ¯¯¯¯¯¯
    ****
    YYYY

In detail:

Selection right operand [sel]
-----------------------------
0. Nested choose/reach selection: behaves the same as for primitive operator @.

        at(2 2↑⍳⍴mat)   ⍝ selects top-left corner of mat

1. Numeric scalar/vector: selects major cells, along the first axis of [old].

        at(2×⍳⌊(≢A)÷2)  ⍝ selects alternate major cells of array A

   The selection, to which left operand [new] is applied, has shape (U,V), where
   U is ≢⍵⍵ and V is 1↓⍴⍵.  With the above alternate major cells example applied
   to an array of shape 10 20 30, the selection will have shape 5 20 30.

2. Function returning a bool mask of rank R: selects from the R-frame of [old].

        at{3 4⍴0 1 1}   ⍝ selects from the 3 4-frame of (say) a 3 4 5 6-array ¹

   The selection, to which left operand [new] is applied, has shape

        U,V; U←+/,S; V←(⍴⍴S)↓⍴⍵; S←⍵⍵ ⍵     ⍝ where ";" means "where" ²

   With  the  above¹ example applied to an array of shape 3 4 5 6, the selection
   will be of shape: (+/,3 4⍴0 1 1),5 6 → 8 5 6.

  ²(muse: Historical note:

        Prior to the adoption of diamond (⋄) as a left-to-right statement separ-
        ator, Sigma APL used semicolon as  a  right-to-left  separator.  Diamond
        eventually triumphed because: "people read APL from left to right". This
        observation, applied to statement order, could have  been  motivated  by
        the procedural mindset "first do this, then do this, then ..."  in which
        we were all steeped at the time.   Conversely, reading Sigma  code  from
        left to right now has a declarative feel if we read ";" as "where":

            x+x; x←4    ⍝ x plus x, where x denotes 4.
   )                                ¯¯¯¯¯

Substitution left operand [new]
-------------------------------
1. If  left  operand  [new] is an array, it is extended to fit the selection, as
   follows.

2. If  the  left  operand is a function, it is applied to the selection, and its
   result [new] is extended to fit the selection, as follows.

If [new] is of shape U and the selection is of shape  (U,V)  (where V can be ⍬),
[new] is replicated along ≢V axes to fit the selection:

    ext ← new ∘.⊣ V⍴0           ⍝ new values extended to fit selection

The  selected  values  of [old] are substituted with the extended array items to
produce [rslt].

A possible conformability indulgence
------------------------------------
Classic indexed assignment ignores unit (length=1) axes when checking conform-
ability:

    M←3 4⍴⎕A                    ⍝ 3 4-matrix

    M[,2;] ← 1 4⍴'abcd'         ⍝ 1 4-matrix replacement of 1 4-selection
    M[,2;] ← 'ijkl'             ⍝   4-vector replacement of 1 4-selection

[at] could indulge its [new] array in similar fashion by ignoring any <1>s in
the shape vector of the [sel]ection. This would mean that a single row matrix
selection could be replaced with a _vector_:

    'ijkl'at{0 1 0} M           ⍝ vector at 1-row matrix selection
···                               ¯¯¯¯¯¯          ¯¯¯¯¯¯

This would be achieved by changing the conformability code in the model from:

    ext ← new ∘.⊣ V⍴0           ⍝ new values extended to fit selection
to:
    ext ← new ∘.⊣ (V~1)⍴0       ⍝ new values extended to fit selection
                   ¯¯¯
Examples:

⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝ Selection conformability:

    1 at {1 0 1} 3 4 5⍴0            ⍝ vector right operand
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1

0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0

1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1

    1 at {3 4⍴1 0} 3 4 5⍴0          ⍝ matrix right operand
1 1 1 1 1
0 0 0 0 0
1 1 1 1 1
0 0 0 0 0

1 1 1 1 1
0 0 0 0 0
1 1 1 1 1
0 0 0 0 0

1 1 1 1 1
0 0 0 0 0
1 1 1 1 1
0 0 0 0 0

    1 at {3 4 5⍴1 0} 3 4 5⍴0        ⍝ rank-3 right operand
1 0 1 0 1
0 1 0 1 0
1 0 1 0 1
0 1 0 1 0

1 0 1 0 1
0 1 0 1 0
1 0 1 0 1
0 1 0 1 0

1 0 1 0 1
0 1 0 1 0
1 0 1 0 1
0 1 0 1 0

    1 at {1} 3 4 5⍴0                ⍝ scalar right operand
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1

1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1

1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1

⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝ Substitution conformability:

    1 at {1 0 1} 3 4 5⍴0            ⍝ scalar left operand
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1

0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0

1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1

    1 2 at {1 0 1} 3 4 5⍴0          ⍝ vector left operand
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1

0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0

2 2 2 2 2
2 2 2 2 2
2 2 2 2 2
2 2 2 2 2

    (2 4⍴⍳8) at {1 0 1} 3 4 5⍴0     ⍝ matrix left operand
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
4 4 4 4 4

0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0

5 5 5 5 5
6 6 6 6 6
7 7 7 7 7
8 8 8 8 8

    (2 4 5⍴⍳40) at {1 0 1} 3 4 5⍴0  ⍝ rank-3 left operand
 1  2  3  4  5
 6  7  8  9 10
11 12 13 14 15
16 17 18 19 20

 0  0  0  0  0
 0  0  0  0  0
 0  0  0  0  0
 0  0  0  0  0

21 22 23 24 25
26 27 28 29 30
31 32 33 34 35
36 37 38 39 40

See also: sam select

Back to: contents

Back to: Workspaces