Conversation started Jan 2, 2020 at 14:30.
Jan 2, 2020 2:30 PM
Anyone here for the APL Cultivation session?
Hello, I'm here for the session.
@AnandChitipothu Ah, cool.
I guess we can get started, and then others can join if and when they show.
Do you have anything in particular you'd like to go through? Otherwise, I was thinking we could go deeper into high-rank (many-dimensional) arrays and how to apply functions to them.
I don't have anything in mind. Lets go with what you suggested.
Jan 2, 2020 2:41 PM
OK, so we have been dealing mostly with vectors (lists) so far, being able to write them as literals like 1 2 3 and 'abc'.
One of the ways to create a higher-rank array is to reshape a vector to a desired shape.
For that we use (Greek Rho for Reshape):
⎕←2 3⍴'abcdef'
@Adám
abc
def
Yes, I've done that earlier. I guess in solving game of life and even in one of the earlier sessions here.
Right. Now ⎕AVU is a long built-in list of semi-random natural numbers, convenient for trying things out:
⎕←2 3 4⍴⎕AVU
@Adám
  0   8   10   13
 32  12    6    7
 27   9 9014  619

 37  39 9082 9077
 95  97   98   99
100 101  102  103
APL shows a blank line to delimit the 2 layers of this 3D array, each of which have 3 rows and 4 columns.
@AnandChitipothu Do you remember how to sort in APL?
Jan 2, 2020 2:45 PM
I like using the following setting in dyalog APL when working with mutli-dimentional arrays.
]boxing on -style=max
⎕←⎕SE.display 2 3 4⍴⎕AVU
@Adám
┌┌→────────────────┐
↓↓  0   8   10   13│
││ 32  12    6    7│
││ 27   9 9014  619│
││                 │
││ 37  39 9082 9077│
││ 95  97   98   99│
││100 101  102  103│
└└~────────────────┘
what is Quad AVU (i'm assuming that is how it is read).
Where do I find help for that?
@AnandChitipothu It, as seen here, does show an indication of every axis, but the actual display of data is the same inside the borders.
@AnandChitipothu You can always hit F1 on it (in your local APL), or:
]help ⎕AVU
Jan 2, 2020 2:48 PM
@AnandChitipothu However, it is really uninteresting. It is the code page for compatibility with pre-Unicode APL.
So we can sort using the tacit function (⊂∘⍋⌷⊢). Do you want an explanation of it?
I'm trying to generate random numbers in a different way other than using ⎕AVU
@AnandChitipothu Just use ? but for what we'll do here, we want to use the same data each time, and the bot cannot remember well.
got it. Lets go with what you have.
trying to decipher tacit.
@AnandChitipothu You could reset the seed for a RNG each time:
⍞←⎕←?⍨100 ⊣ ⎕RL←1
@Adám 2 85 98 72 32 60 70 38 17 44 64 66 30 59 100 99 20 69 29 67 6 68 75 24 56 41 89 21 53 15 23 91 78 84 92 86 14 34 81 79 95 94 11 83 63 43 45 52 12 88 16 49 65 31 57 8 73 76 55 4 42 3 9 35 1 18 46 19 71 25 37 90 48 82 7 80 26 47 22 40 33 93 36 27 13 77 74 58 28 96 54 97 62 61 39 87 51 10 5 50
Jan 2, 2020 2:53 PM
⍞←⎕←?⍨10 ⊣ ⎕RL←1
@Adám 2 5 10 8 4 6 9 3 1 7
⍞←⎕←?⍨100 ⊣ ⎕RL←1
@Adám 2 85 98 72 32 60 70 38 17 44 64 66 30 59 100 99 20 69 29 67 6 68 75 24 56 41 89 21 53 15 23 91 78 84 92 86 14 34 81 79 95 94 11 83 63 43 45 52 12 88 16 49 65 31 57 8 73 76 55 4 42 3 9 35 1 18 46 19 71 25 37 90 48 82 7 80 26 47 22 40 33 93 36 27 13 77 74 58 28 96 54 97 62 61 39 87 51 10 5 50
But ⎕AVU is fine for now.
So the sorting function says ⊂∘⍋ the enclosed grade indexes into the argument.
Because i j k⌷data is like data[i;j;k].
But we only want an i so we can reorder along the leading dimension. That's why i needs to be enclosed.
(⊂∘⍋⌷⊢) is equivalent to {(⊂⍋⍵)⌷⍵}
Jan 2, 2020 2:57 PM
I'm trying to understand each symbol.
is the right (and in this case only) argument, pointing its finger to the right.
is the index function which is [ and ] printed on top of each other.
⍞←⍋ 10 ⍴ ⎕AVU
@AnandChitipothu 1 7 8 2 10 3 6 4 9 5
⍞←10 ⍴ ⎕AVU
@AnandChitipothu 0 8 10 13 32 12 6 7 27 9
Jan 2, 2020 2:59 PM
is grade up (like an airplane going up), it gives the indices that would sort the argument.
is enclose, packages its argument into a scalar.
why are we enclosing?
Because allows selection along each axis:
⎕←2 3 4⍴⎕AVU ⋄ ⎕←2 1 3⌷⎕AVU
@Adám
  0   8   10   13
 32  12    6    7
 27   9 9014  619

 37  39 9082 9077
 95  97   98   99
100 101  102  103
LENGTH ERROR
Sorry:
⎕←2 1 3⌷2 3 4⍴⎕AVU ⋄ ⎕←(2 3 4⍴⎕AVU)[2;1;3]
@Adám
9082
9082
Jan 2, 2020 3:01 PM
See the correspondence between i j k⌷data and data[i;j;k]?
⍞←(⊂∘⍋⌷⊢) 4 5 ⍴ ⎕AVU
@AnandChitipothu    0   8 10 13   32
You need ⎕← to display multiple lines:
⎕←(⊂∘⍋⌷⊢) 4 5 ⍴ ⎕AVU
@Adám
   0   8 10 13   32
  12   6  7 27    9
9014 619 37 39 9082
9077  95 97 98   99
Compare to the unsorted:
⎕←4 5 ⍴ ⎕AVU
Jan 2, 2020 3:03 PM
@Adám
   0   8 10 13   32
  12   6  7 27    9
9014 619 37 39 9082
9077  95 97 98   99
Heh, in this case it was already sorted.
both are same. it is not sorting.
@AnandChitipothu It is sorted. Let's try this one instead:
⎕←3 4⍴⎕AVU
@Adám
 0  8   10  13
32 12    6   7
27  9 9014 619
⎕←(⊂∘⍋⌷⊢)3 4⍴⎕AVU
Jan 2, 2020 3:04 PM
@Adám
 0  8   10  13
27  9 9014 619
32 12    6   7
Noticed that the last two rows swapped position.
yes. Is it sorting based on the first element only? (the first column)
No, but the major cells (which in a matrix are the rows) are sorted lexicographically. Since they differ in the first position, there's no need to look further.
⎕←(⊂∘⍋⌷⊢)'aacc' 'baab' 'aabc'
@Adám
┌────┬────┬────┐
│aabc│aacc│baab│
└────┴────┴────┘
⎕←(⊂∘⍋⌷⊢)3 4⍴'aaccbaabaabc'
Jan 2, 2020 3:06 PM
@Adám
aabc
aacc
baab
Here it had to look at the third element of each row to sort the two that begin with 'aa'.
@Adám got it.
Now by defining our functions in terms of the leading axis, like we've done with the sorting here, we can use the "Rank" operator to tell APL which sub-arrays we want the function to be applied to.
Could you please explain:

(⊂∘⍋⌷⊢) is equivalent to {(⊂⍋⍵)⌷⍵}
For sure. The curly braces makes an "explicit" (as in it does mention its argument ) function.
The tacit function (in round parenthesis) uses the train syntax where the first and third function (counting from the right) are applied directly to the argument, while the second function is applied between their results.
Jan 2, 2020 3:10 PM
I understood how {(⊂⍋⍵)⌷⍵} is working. I'm confused about how ⊢ which gives the right element is doing the magic.
We have a rule that for three functions f g h and the array Y the syntax (f g h)Y means (f Y) g (h Y)
@AnandChitipothu is simply a no-op function applied to the argument, which of course gives the argument.
we are using ⊢ in the monadic form, which is identity function.
got it. Thanks!
can we try another train function before we move on?
Yes. Maybe I should have said that (⊂∘⍋⌷⊢) is equivalent to {(⊂∘⍋⍵)⌷(⊢⍵)}
which in turn can be simplified to {(⊂⍋⍵)⌷⍵}
Jan 2, 2020 3:13 PM
That makes it pretty clear.
Let's do average (arithmetic mean): (+⌿÷≢) (but the last character inside the parenthesis may render funny if you use Chrome. It should be with / overlay)
I'm on firefox and it looks fine
OK, good. It is the sum +⌿ divided by ÷ the tally
Exercise: Can you give me the equivalent explicit function?
let me think...
{(+⌿⍵)÷(≢⍵)}
Yes, very good.
How about the other direction. Say we have a "normalise" function {⍵÷+⌿⍵}. Can you make that into a train?
Jan 2, 2020 3:18 PM
thinking...
what is the function to swap arguments?
@AnandChitipothu The operator: X f⍨ Y is Y f X but you shouldn't need it here.
Got it.

⎕←(⊢÷+⌿) 1 2 3
⎕←(⊢÷+⌿) 1 2 3
@AnandChitipothu
0.1666666667 0.3333333333 0.5
Right!
I think I got a hang of trains. Thanks!
Jan 2, 2020 3:23 PM
Of course.
Now lets go back to
⎕←2 3 4⍴⎕AVU
@Adám
  0   8   10   13
 32  12    6    7
 27   9 9014  619

 37  39 9082 9077
 95  97   98   99
100 101  102  103
The whole array has rank 3. The layers have rank 2, and the rows have rank 1.
Now while the array as a whole is sorted, the individual layers are not (well, the first layer isn't).
Yes. If sort the first layer, the last two rows get swapped.
We can take our sorting function and apply it rank-2-wise:
Oops.
@Adám
SYNTAX ERROR
Jan 2, 2020 3:26 PM
⎕←(⊂∘⍋⌷⊢)⍤2⊢2 3 4⍴⎕AVU
@Adám
  0   8   10   13
 27   9 9014  619
 32  12    6    7

 37  39 9082 9077
 95  97   98   99
100 101  102  103
is a dyadic operator which takes a function on its left, and on the right it takes a specification of which sub-arrays we want to apply that function to.
The extra to the right of ⍤2 is there to separate the 2 from 2 3 4 so they don't form the 4-element vector 2 2 3 4.
Some of the rows are not sorted either (last two rows of first layer, and first row of second layer).
Task: instead of sorting the layers' rows, sort all six rows instead.
Let me try..
⎕←(⊂∘⍋⌷⊢)⍤1⊢2 3 4⍴⎕AVU
@AnandChitipothu
  0   8   10   13
  6   7   12   32
  9  27  619 9014

 37  39 9077 9082
 95  97   98   99
100 101  102  103
Exactly.
The sorting function preserves the shape of the data it sorts. But some functions change the shape. That's not a problem either. Let's e.g. drop the first layer:
⎕←1↓2 3 4⍴⎕AVU ⋄ ⎕←⍴1↓2 3 4⍴⎕AVU
Jan 2, 2020 3:33 PM
@Adám
 37  39 9082 9077
 95  97   98   99
100 101  102  103
1 3 4
Notice that the resulting shape is 1 3 4 not 3 4. We still have the same number of axes, we just shortened the array along one axis.
Task: Drop the first row from each layer.
Do we need to do the reverse of ⊂ if we just want 3 4?
@AnandChitipothu No, that wouldn't work. But would do it: 1⌷1↓2 3 4⍴⎕AVU
Now can you drop one row from each layer?
Jan 2, 2020 3:37 PM
trying...
I tried with each ¨, but that didn't work.
@AnandChitipothu No, use like before. Think about what we want to see. The right argument should have which rank?
⎕←1↓⍤2⊢2 3 4⍴⎕AV
@AnandChitipothu


	⌶ɫ

_abc
defg
⎕←1↓⍤2⊢2 3 4⍴⎕AVU
@AnandChitipothu
 32  12    6   7
 27   9 9014 619

 95  97   98  99
100 101  102 103
Jan 2, 2020 3:43 PM
Yup.
And if we want to remove the first column (=element) from each row, we'd use 1↓⍤1
Let's say we have a table like:
⎕←4 3⍴⎕AVU
@Adám
 0    8  10
13   32  12
 6    7  27
 9 9014 619
And now we want to increase these values by some multipliers. The first row should be multiplied by 3, the second by 1, the third by 4 and the last one by 1.
In other words, we want 3 1 4 1×4 3⍴⎕AVU
Bu we can't just do the multiplication, as you can't multiply a vector by a matrix:
⎕←3 1 4 1×4 3⍴⎕AVU
@Adám
RANK ERROR
help on ⍤ has an example.
Instead, we need to think about what we want × to see.
Yeah, so we say that on the left, we want × to see scalars (individual numbers) which have rank 0 and on the right we want the rows which have rank 1:
⎕←3 1 4 1×⍤0 1⊢4 3⍴⎕AVU
Jan 2, 2020 3:49 PM
@Adám
 0   24  30
13   32  12
24   28 108
 9 9014 619
Is it possible to pass an array of more than 2 elements as argument to ⍤?
hello
how are you all?
Hello @ThePuzzlerThree.
@AnandChitipothu As rank-specifying operand? Yes, it can take up to three which means (monadic,left,right).
@ThePuzzlerThree Very well. We're in the middle of a APL learning session. Interested in APL?
im here to learn what it actually is from a human and not wikipedia
Jan 2, 2020 3:53 PM
@Adám can you please show me an example?
@ThePuzzlerThree OK, can you hang around for 10 mins until the lesson is over, and I'll give you a personalised intro?
@AnandChitipothu Yes. Give me a min.
mension me so i get the notification when u r ready
Of course.
Jan 2, 2020 3:54 PM
i cant spell
@AnandChitipothu OK, while a bit contrived, look at this:
⎕←⊖2 3 4⍴⎕AVU
@Adám
 37  39 9082 9077
 95  97   98   99
100 101  102  103

  0   8   10   13
 32  12    6    7
 27   9 9014  619
So this flips the array upside down. We could also give it rank 3 to produce the same result (as the array has rank 3):
⎕←⊖⍤3⊢2 3 4⍴⎕AVU
@Adám
 37  39 9082 9077
 95  97   98   99
100 101  102  103

  0   8   10   13
 32  12    6    7
 27   9 9014  619
However, dyadic is rotate with the left argument specifying the number of steps. When given a vector on the left and a matrix on the right, it rotates (cyclically) each column of the matrix by the specified amount:
⎕←0 1 0 1⊖2 3⍴⎕AVU
Jan 2, 2020 3:57 PM
@Adám
LENGTH ERROR
oops
⎕←0 1 0 1⊖3 4⍴⎕AVU
@Adám
 0 12   10   7
32  9    6 619
27  8 9014  13
⎕←3 4⍴⎕AVU
@AnandChitipothu
 0  8   10  13
32 12    6   7
27  9 9014 619
Notice that columns 2 and 4 were rotated one step.
We could do this for each layer of our rank-3 array:
Jan 2, 2020 3:59 PM
interesting...
is dyalog apl a bot?
⎕←0 1 0 1⊖⍤1 2⊢3 4⍴⎕AVU
@Adám
 0 12   10   7
32  9    6 619
27  8 9014  13
@ThePuzzlerThree Yes.
Jan 2, 2020 3:59 PM
oops again
⎕←0 1 0 1⊖⍤1 2⊢2 3 4⍴⎕AVU
@Adám
  0  12   10    7
 32   9    6  619
 27   8 9014   13

 37  97 9082   99
 95 101   98  103
100  39  102 9077
Now we can define single function which, when applied monadically flips the entire array, but when used dyadically it uses a vector on the left to rotate the layers on the right: ⊖⍤3 1 2
⎕←⊖⍤3 1 2⊢2 3 4⍴⎕AVU
@Adám
 37  39 9082 9077
 95  97   98   99
100 101  102  103

  0   8   10   13
 32  12    6    7
 27   9 9014  619
⎕←0 1 0 1⊖⍤3 1 2⊢2 3 4⍴⎕AVU
@Adám
  0  12   10    7
 32   9    6  619
 27   8 9014   13

 37  97 9082   99
 95 101   98  103
100  39  102 9077
Jan 2, 2020 4:02 PM
@AnandChitipothu Makes sense?
Time's up for this session, but I suggest we continue in 2-3 weeks with more advanced usages of .
am i in the right shell if i type one and => 1 appears?
@ThePuzzlerThree No. You seek to use an APL "shell" (REPL)?
.....
i use python so i call it that
@ThePuzzlerThree Have you downloaded an APL system?
Thanks a lot @Adám. Quite enlightening session. I'm still trying to understand the monadic use.
Jan 2, 2020 4:05 PM
no
@AnandChitipothu Go experiment! If you are exploring monadic use, try using the function as it will enclose what it sees, showing you what whichever function you'd use instead would see.
Thanks. I'll continue to experiment. Looking forward for the next session. I'll try to come better prepared next time.
 
Conversation ended Jan 2, 2020 at 16:07.