/\⌿⍀,⍪#

Replicate /#

Next up is /. When what’s on its left is an array rather than a function it instead acts like a function, which makes it unusual. We cover the operator case of / elsewhere, e.g. +/ for sum.

As a function, / is called replicate. It replicates each element on the right to as many copies as indicated by the corresponding element on the left:

1 1 2 1 2 1 2 1/'Misisipi'
Mississippi

A more common usage is with a Boolean left argument, where it then acts as a filter:

1 0 1 1 0 0 1 0 1 1 1/'Hello World'
HllWrld

It has one more trick: if you use a negative number, then it replaces the corresponding element with that many prototypes (spaces for characters and zeros for numbers):

1 1 ¯1 1 1/'Hello'
He lo

You can also use a single scalar to “empty” an array:

0/'abc'
1/'abc' 
abc

1/x can also be used to ensure that x has at least one dimension (it ravels scalars, leaving all other arrays untouched):

1/8   ⍝ Scalar becomes vector, rank 1
1/8 8 ⍝ Higher ranks remain untouched
1
2

Expand \#

/ has a cousin, \, which, when used as a function, is called expand.

Positive numbers on the left also replicate like with / but negative numbers insert that many prototypical elements at that position:

1 1 ¯1 1 1 1\1 2 3 4 5
1 2 0 3 4 5

You can use 0 instead of ¯1 which makes it convenient to use Boolean left arguments.

We can now begin to see how we can insert into an array. Let’s go back to the problem of inserting 3 in between 2 and 4 in the list 1 2 4 5. Our method was:

Get the indices of the elements:

⍳≢1 2 4 5
1 2 3 4

Look where the index is 2:

2=⍳≢1 2 4 5
0 1 0 0

That’s where we want to expand:

1+2=⍳≢1 2 4 5
1 2 1 1

Use \ to perform the expansion:

(1+2=⍳≢1 2 4 5)\1 2 4 5 
1 2 2 4 5

Replace the extra 2 with our desired element:

3@(1+2)(1+2=⍳≢1 2 4 5)\1 2 4 5
1 2 3 4 5

Just like the operators / and \ each have a sibling, and which do the same thing but along the first axis (i.e. on the major cells) so to with the functions / and \:

(1 0 1/3 3⎕A) (1 0 13 3⎕A)
(1 ¯2 1 1\3 3⎕A) (1 ¯2 1 13 3⎕A)
┌──┬───┐
│AC│ABC│
│DF│GHI│
│GI│   │
└──┴───┘
┌─────┬───┐
│A  BC│ABC│
│D  EF│   │
│G  HI│   │
│     │DEF│
│     │GHI│
└─────┴───┘

Ravel ,#

Monadic , ravels. It takes all the scalars of an array and makes a single vector (list) out of them. This includes a scalar, so ,3 is a one-element vector:

3 3⎕A
,3 3⎕A
ABC
DEF
GHI
ABCDEFGHI

Question:

Isn’t that the same as monadic ?

It is not. For example,

3 3⎕A
3 3 3⍴⍳27
ABCDEFGHI
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

The difference is that will take all the data and make it a simple vector. , will take all the scalars and make it a (potentially nested) vector:

2 2'abc' 'def' 'ghi' 'jkl'
,2 2'abc' 'def' 'ghi' 'jkl' 
abcdefghijkl
┌───┬───┬───┬───┐
│abc│def│ghi│jkl│
└───┴───┴───┴───┘

is the same as recursive application of ⊃,/.

Catenate ,#

Which brings us to dyadic ,, catenate, which is simply concatenation:

1 2 3,4 5 6
1 2 3 4 5 6

, can also get specified an axis upon which to act:

(2 3⎕A),[1](2 3⍴⍳6)
(2 3⎕A),[2](2 3⍴⍳6) 
A B C
D E F
1 2 3
4 5 6
ABC 1 2 3
DEF 4 5 6

You can even use fractional axes to specify that you want to concatenate along a new inserted axis between the next lower and higher integer axes:

(2 3⎕A),[0.5](2 3⍴⍳6) ⍝ 3D array
(2 3⎕A),[1.5](2 3⍴⍳6) ⍝ 3D array 
A B C
D E F

1 2 3
4 5 6
A B C
1 2 3

D E F
4 5 6

This works for the monadic form too:

,[0.5]2 3⎕A
⍴,[0.5]2 3⎕A
,[1.5]2 3⎕A
⍴,[1.5]2 3⎕A
ABC
DEF
1 2 3
ABC

DEF
2 1 3

Catenate first #

Then we have . The dyadic is a synonym for ,[1], and it’s sometimes referred to as catenate first:

(2 3⎕A),[1](2 3⍴⍳6)
(2 3⎕A)(2 3⍴⍳6)
A B C
D E F
1 2 3
4 5 6
A B C
D E F
1 2 3
4 5 6

Table #

Monadic is called table as it ensures that the result is a table. It ravels the major cells of an array and makes each one of them into a row (i.e. a major cell) of a matrix:

2 3 4⎕A
2 3 4⎕A
ABCD
EFGH
IJKL

MNOP
QRST
UVWX
ABCDEFGHIJKL
MNOPQRSTUVWX

That is, monadic is just a synonym for ,⍤¯1 (except for scalars). To be universal, we’d need to say {,⍤¯1⊢1/⍵}.