What does enclose do in APL?

Viewed 48

I have this array which is called x

       x
 0 0 1 0 1 1 1 1 
 0 1 0 1 1 0 1 1 
 0 1 1 0 1 0 1 1 
 1 1 0 1 1 0 0 1 

Supposedly something is happening when I enclose x using ⊂x but I see no difference:

      ⊂x
 0 0 1 0 1 1 1 1 
 0 1 0 1 1 0 1 1 
 0 1 1 0 1 0 1 1 
 1 1 0 1 1 0 0 1 

What's going on here?

3 Answers

Connor answered correctly that it is enclosed but the default display form makes it difficult to see. There should be extra spacing to the left of your output.

Turning ]box on helps show the structure of nested displays visually, but there are also more concrete ways to understand what enclosing is.

      x←2 3⍴⎕A
      x
ABC
DEF
      ⊂x
 ABC
 DEF
      ]box on
Was OFF
      ⊂x
┌───┐
│ABC│
│DEF│
└───┘

In short, enclosing wraps any array to be inside a scalar, so that it can be included as an element of another array. This is the principle behind general nested arrays - it's arrays all the way down.

How can we determine the structure of arrays without guessing based on visual output?

Nested arrays have depth, which is different to rank in APL. Rank is the number of dimensions an array has (scalar 0, vector 1, matrix 2 etc.) whereas depth is how many arrays are inside your arrays.

The depth function ≡⍵ returns the depth of an array. The absolute value of depth |≡⍵ is the level of nesting, starting at 0 for simple scalars.

      ≡'a'  ⍝ Simple scalar has depth 0
0
      ≡x    ⍝ Simple matrix has depth 1
1
      ≢⍴x   ⍝ Simple matrix has rank 2
2
      ≡⊂x   ⍝ Enclosing increases the depth
2
      ≡⊂⊂x
3
      ≡⊂⊂⊂x
4

Negative depth indicates uneven nesting:

      ≡(1 2)(3 4)         ⍝ Evenly nested arrays have positive depth
2
      ≡(1 2)(3 4 (4 5))   ⍝ Unevenly nested arrays have negative depth
¯3

If you have a complex structure like this, you can use Each () to keep drilling down until you feel you have a better understanding.

      ⎕ ← nv ← (1 2)(3 4 (4 5))
┌───┬─────────┐
│1 2│┌─┬─┬───┐│
│   ││3│4│4 5││
│   │└─┴─┴───┘│
└───┴─────────┘

      ⍴nv     ⍝ 2-element vector
2
      ≡nv     ⍝ Unevenly nested
¯3

      ⍴¨nv    ⍝ 2 vectors of lengths 2 and 3
┌─┬─┐
│2│3│
└─┴─┘
      ≡¨nv    ⍝ 1st element is simple, 2nd is unevenly nested
1 ¯2

      ⍴¨¨nv   ⍝ 2nd element appears to be made of 2 scalars followed by a vector
┌───┬─────┐
│┌┬┐│┌┬┬─┐│
││││││││2││
│└┴┘│└┴┴─┘│
└───┴─────┘
      ≡¨¨nv   ⍝ 2nd element is 2 simple scalars and a non-nested array
┌───┬─────┐
│0 0│0 0 1│
└───┴─────┘

So we can tell we have a 2 element nested vector. The 1st element is a simple 2-element vector. The 2nd element contains 2 simple scalars and a simple vector of length 2.

So why does an array need to be enclosed to be part of another array?

Arrays in APL are always made of scalars (rank-0 arrays) as their elements.

So the vector 1 2 3 is made of three scalar numbers, and 2 3⍴⎕A is made of 6 scalar characters arranged in 2 rows with 3 columns.

A simple scalar is a single character, a single number or a single namespace reference. Enclosing simple scalars is a no-op:

      3 ≡ ⊂⊂⊂⊂⊂⊂3
1

However, we can include any array as part of another array by enclosing it.

      x ← 2 3⍴⎕A   ⍝ x is a simple matrix
      3⍴x          ⍝ Reshape uses the elements within
ABC
      3⍴⊂x         ⍝ Enclosing turns the whole array into an element
┌───┬───┬───┐
│ABC│ABC│ABC│
│DEF│DEF│DEF│
└───┴───┴───┘

Placing arrays (literal or named) next to each other in Dyalog and other APLs is called stranding, and implicitly encloses them:

      x x x   ⍝ Stranding to create a nested vector
┌───┬───┬───┐
│ABC│ABC│ABC│
│DEF│DEF│DEF│
└───┴───┴───┘
      x,x,x   ⍝ Catenate to build up a larger simple matrix
ABCABCABC
DEFDEFDEF

This makes the convenient notation of 1 2 3 4 to build up lists with numbers or 'A' 'B' 'C' 'D' (shortened as 'ABCD') to make lists of characters consistent with x x x x for any array x.

It is enclosed, but it's difficult to tell.

To see enclosures in your IDE run this command:

]Box ON

Now you'll see something like this:

      ⊂x
┌───────────────┐
│0 0 1 0 1 1 1 1│
│0 1 0 1 1 0 1 1│
│0 1 1 0 1 0 1 1│
│1 1 0 1 1 0 0 1│
└───────────────┘

P.S. In general, for more info about commands run:

]

it will guide you the rest of the way.

Boxing is useful while learning and debugging, but the "discreet" display is very much by design and useful when writing simple applications. For example, it is trivial to do simple report formatting with minimal effort:

      data←+\?3 4⍴100 ⍝ cumulative sales figures
     'Sales' 'Q1' 'Q2' 'Q3' 'Q4'⍪'East' 'West' 'Central' 'Total',data⍪+⌿data
 Sales     Q1   Q2   Q3   Q4 
 East      82  180  220  255 
 West      38   43   96  160 
 Central   63   84  145  190 
 Total    183  307  461  605 

Related