Conversation started Nov 1, 2017 at 18:30.
Nov 1, 2017 18:30
Welcome to everyone here for the APL learning session.
So in the previous lessons we covered APL arrays and how to use functions. Any ideas for today's subject?
@EriktheOutgolfer That's a possibility, though we did touch upon them fairly well during the last session.
If there are no other bids, I'll go through the built-in operators.
I want to know how to enter funny characters into GNU APL, but that might be too basic
@barrycarter For keyboarding info, have a look here
@Adám Thanks!
Nov 1, 2017 18:33
also here we usually do dyalog apl
We could also spend some time on keyboard mnemonics.
@EriktheOutgolfer Yeah, but we don't have to, all APLs are on-topic (maybe not Jelly).
I used to use APL+ before I came to Dyalog.
Oh, OK, I'm using GNU APL, and it's command line-- no fonts... but I also have tryapl.org in another tab
@Adám that's why I said "usually" ;) (also Jelly isn't an APL but instead an APL 2nd-generation child)
@barrycarter You can download Dyalog APL for free. It has nice GUI.
OK, let's go through some operators.
The first operator is /. It is a monadic operator which derives an ambivalent function.
@All please interrupt if I use terminology you don't understand!
@Adám What's an ambivalent function?
Nov 1, 2017 18:36
monadic = takes one argument?
@DJMcMayhem A function which can be called monadically or dyadically.
Like f(x) or f(x,y) in mathematics?
E.g. - is ambivalent. Monadically it is negate, dyadically it is subtraction.
/.5 is -5 but /. 5 6 is -1?
@barrycarter Yes, but dyadic APL functions are infix. (Usually called operators in other languages)
Nov 1, 2017 18:38
Am I allowed to ask why they didn't just use "-"?
5 /. 6 is -1 then?
@barrycarter Uh, that doesn't look like APL to me.
OK, NM, I don't know enough APL.
@barrycarter yeah not sure what you mean here
@barrycarter - is indeed negate/subtraction in APL. I was just giving an example of an ambivalent function in APL.
Oh, got it. So now you're describing the "/" operator?
Nov 1, 2017 18:40
Yes. +/ is a derived ambivalent function. The monadic function is plus-reduction (i.e. sum) and the dyadic function is windowed sum, as in sliding windows of size (shorthand for "left argument")
#TIO run apl-dyalog ⎕←+/3 1 4 1 5
#TIO run apl-dyalog ⎕←2 +/ 3 1 4 1 5
@Adám
4 5 5 6
#TIO run apl-dyalog ⎕←3 +/ 3 1 4 1 5
@Adám
8 6 10
Nov 1, 2017 18:41
Neat, n+/ means apply + to each subsequence of n elements
@barrycarter Yep.
What does 3-/ do? Subtraction isn't associative.
#TIO run apl-dyalog ⎕← 3-/ 1 2 3 4 5
@barrycarter

Real time: 0.027 s
User time: 0.005 s
Sys. time: 0.019 s
CPU share: 86.85 %
Exit code: 0
@barrycarter You need ⎕← in front to print.
@barrycarter f/ and n f/ inserts the function f in between the elements and whatever that evaluates to, is the result.
Nov 1, 2017 18:44
#TIO run apl-dyalog ⎕← 3-/ 1 2 3 4 5
@barrycarter
2 3 4
So 1 - 2 - 3 is 2?
So, because functions in APL are right-associative, -/⍵ (this is a shorthand which means the monadic form of -/) is alternating sum.
@barrycarter Yes, 1 - (2 - 3)
Ah, got it. Not left to right.
f/⍵ is called Reduce because it reduces the rank of its argument by 1.
Nov 1, 2017 18:46
So, if I apply it to a matrix, I'll get back a vector?
@barrycarter Yes. Even if the function you provide does not "combine" its arguments.
#TIO run apl-dyalog ⎕←{'(',⍺,⍵,')'}/'Hello'
@Adám
 (H(e(l(lo))))
Here, the function I gave concatenates its arguments and parentheses.
If you look really carefully, you'll see that there is a space in front of the leftmost (
This is APLs way to indicate that the array (a character vector) is enclosed. I.e. it returned ⊂'(H(e(l(lo))))'
#TIO run apl-dyalog ⎕←{'(',⍺,⍵,')'}/ h e l l o
@barrycarter
line(1,0) : error AC0505: error (VALUE ERROR) executing line "⎕←{'(',⍺,⍵,')'}/ h e l l o"
                                                              ^
Complete: 1 error.
DOMAIN ERROR: There were errors processing the script
 '#'⎕NS ⎕FIX'file:///home/runner/.bin.tio.dyalog'
∧

Real time: 0.030 s
User time: 0.004 s
Sys. time: 0.022 s
CPU share: 87.13 %
Exit code: 0
Nov 1, 2017 18:50
#TIO run apl-dyalog ⎕←(⊂'(H(e(l(lo))))') ≡ {'(',⍺,⍵,')'}/'Hello'
@barrycarter You need singlequotes around the string.
Sorry, I'll stop doing that.
@barrycarter No, it is fine.
Shouldn't it be the same as applying the function to 'h' '... oh wait
#TIO run apl-dyalog ⎕←{'(',⍺,⍵,')'}/ 'h' 'e' 'l' 'l' 'o'
Nov 1, 2017 18:51
@barrycarter
 (h(e(l(lo))))
@barrycarter Yes, "strings" in APL are just vectors of scalar characters. See Lesson 1.
We can also apply reductions to higher-rank arrays:
#TIO run apl-dyalog ⎕←3 4⍴⍳12
@Adám
1  2  3  4
5  6  7  8
9 10 11 12
#TIO run apl-dyalog ⎕←+/3 4⍴⍳12
@Adám
10 26 42
#TIO run apl-dyalog ⎕←+2/3 4⍴⍳12
Nov 1, 2017 18:53
@barrycarter
1 1  2  2  3  3  4  4
5 5  6  6  7  7  8  8
9 9 10 10 11 11 12 12
Notice how the rank went down from 2 to 1 (i.e. matrix to vector). Reductions lower the rank.
#TIO run apl-dyalog ⎕←2+/3 4⍴⍳12
@barrycarter
 3  5  7
11 13 15
19 21 23
N f/ is called N-wise reduce, and does not lower the rank. As barrycarter neatly showed.
So it only reduces when each row is reduced to a single element.
#TIO run apl-dyalog ⎕←4+/3 4⍴⍳12
Nov 1, 2017 18:55
@barrycarter
10
26
42
Ah! Using 4+ is different from just doing +
@barrycarter No, N-wise reduce does not lower the rank.
@barrycarter Right. This may be handy in golfing…
Notice that / goes along the trailing axis, i.e. the it reduced the rows of the matrix. It has a twin, which goes along the first axis, i.e. the columns of a matrix.
why just golfing? n-wise reduce can remove the need to map reduce after making pairs first, and that can get tedious
@EriktheOutgolfer Well then, all the more power to you.
#TIO run apl-dyalog ⎕←+⌿3 4⍴⍳12
@Adám
15 18 21 24
Nov 1, 2017 18:57
So these are the column sums.
What if you have a rank 3 tensor... can you specify which sum you want?
@barrycarter Yes, you can use f/[dimension]
#TIO run apl-dyalog ⎕←+/1 4⍴⍳12
@barrycarter
10
#TIO run apl-dyalog ⎕←2 3 4⍴⍳24
Nov 1, 2017 19:00
@Adám
 1  2  3  4
 5  6  7  8
 9 10 11 12

13 14 15 16
17 18 19 20
21 22 23 24
#TIO run apl-dyalog ⎕←+/[1] 4⍴⍳12
@barrycarter
10
#TIO run apl-dyalog ⎕←(+⌿2 3 4⍴⍳24)(+/[2]2 3 4⍴⍳24)(+/2 3 4⍴⍳24)
@Adám
 14 16 18 20  15 18 21 24  10 26 42
 22 24 26 28  51 54 57 60  58 74 90
 30 32 34 36
OK, I expected that to do the same thing as just "+/"
Nov 1, 2017 19:01
@barrycarter f/[1] is f⌿
Do I mean f/[0]?
#TIO run apl-dyalog ⎕←+/[2] 3 4⍴⍳12
@Adám
10 26 42
Finally :-D
Ah, OK, but shouldn't +/[1] also give multiple columns (ie, a vector?)
Nov 1, 2017 19:03
11 messages moved to trash
#TIO run apl-dyalog ⎕←+/[1] 3 4⍴⍳12
@barrycarter
15 18 21 24
@barrycarter It preserves the 2D layout of the columns.
OK, that's what I expected.
So we did /'s twin. Now we'll look at its cousin.
\
While / is reduction, \ is cumulative reduction:
#TIO run apl-dyalog ⎕←+\3 1 4 1 5
Nov 1, 2017 19:05
@Adám
3 4 8 9 14
So, for obvious reasons, f\ does not reduce rank either.
@barrycarter Multiplication is ×
I was trying to get 1 thru 7 factorial.. ah
* is power!
@barrycarter Not the letter "x", the actual Unicode times sign.
#TIO run apl-dyalog ⎕← ×\ 1 2 3 4 5 6 7
@barrycarter
1 2 6 24 120 720 5040
Nov 1, 2017 19:07
There we go
2 messages moved to Trash
2 messages moved to Trash
Yes. But of course, you can just use ! for factorial.
> Adam has invite you to join trash. See your invitations.
I am somewhat confused
@SocraticPhoenix message cleanup, ignore
because adam trashed lengthy errors and that invites you
Nov 1, 2017 19:09
/'s cousin \ of course has a twin too; . No need to explain, I presume.
And \[n] doubtless?
@barrycarter Yes.
#TIO run apl-dyalog ⎕←+\ 3 4⍴⍳12
@barrycarter
1  3  6 10
5 11 18 26
9 19 30 42
@All That's four operators for you. Can we move on to another operator? Questions?
Nov 1, 2017 19:10
#TIO run apl-dyalog ⎕←+[2] 3 4⍴⍳12
@barrycarter
1  3  6 10
5 11 18 26
9 19 30 42
#TIO run apl-dyalog ⎕←2+\ 3 4⍴⍳12
@barrycarter
line(1,0) : error AC0505: error (SYNTAX ERROR) executing line "⎕←2+\ 3 4⍴⍳12"
                                                               ^
Complete: 1 error.
DOMAIN ERROR: There were errors processing the script
 '#'⎕NS ⎕FIX'file:///home/runner/.bin.tio.dyalog'
∧

Real time: 0.032 s
User time: 0.007 s
Sys. time: 0.021 s
CPU share: 86.61 %
Exit code: 0
@Adám I'm a bit unclear on the behavior of /[n]
@Adám Does there exist a function that can reduce Vectors of more than one type?
Nov 1, 2017 19:11
@EriktheOutgolfer It selects the axis to be collapsed (reduced).
i.e 1 2 'abc'
@Adám ...
I get it
@H.PWiz I'm guessing you'd need an operation that can be applied to both numbers and letters?
@H.PWiz Sure. Like we saw concatenation before. But any structural function will do.
the [] is there so that it's not confused with the right array
Nov 1, 2017 19:13
@EriktheOutgolfer Yes, it doesn't quite fit into the syntax. If you want clean syntax, use . But we can get back to that.
@H.PWiz You can also use a user-defined function with reduce. All APL operators apply to all APL functions. Period.
OK, the next operator is ¨ which is called "Each" for a good reason. f¨⍵ applies the function f monadically to each element of .
So f/ fails if f is solely monadic?
@barrycarter Yes. It has to, no?
No, it could do what f'' or whatever does
@barrycarter the two operators are separate for clarity I guess
@barrycarter That wouldn't make sense. Then use .
Nov 1, 2017 19:16
and because user-defined functions which can be called either monadically or dyadically
@barrycarter And because many functions, especially primitives (built-ins) are ambivalent.
Right. I'm just saying that having f/ apply to each element individually would be a reasonable extension if f is monadic, but continue.
apl isn't a golfing language :p
@barrycarter ⍺ f¨ ⍵ applies f between the paired-up elements of and .
#TIO run apl-dyalog ⎕← (1 2 3) + (4 5 6)
Nov 1, 2017 19:17
@barrycarter
5 7 9
#TIO run apl-dyalog ⎕← 1 2 3 , 4 5 6
@Adám
1 2 3 4 5 6
#TIO run apl-dyalog ⎕← 1 2 3 ,¨ 4 5 6
@Adám
 1 4  2 5  3 6
@Adám is there a way other than using to map on one side only?
Nov 1, 2017 19:19
How is what i did different from +'' ?
#TIO run apl-dyalog ⎕← 1 2 3 ,¨ (10 20)(30 40)(5 6)
@Adám
 1 10 20  2 30 40  3 5 6
@EriktheOutgolfer No. (I actually just wrote a new operator for that yesterday.) But if your arrays are regular (non-ragged) you should be using high-rank arrays instead, and then you can use .
@barrycarter Most arithmetic functions are "scalar" meaning they penetrate to the very leaves of the arrays. ¨ is meaningless for scalar functions.
@Adám another reason both rank and depth in the same language can be beneficial if tamed correctly
@Adám very sorry, but I have to off wifi now. @ThomasWard said he was trying to set up an instance of the bot, so hopefully that works out... I should be able to respond to question about it on my phone if necessary :)
Nov 1, 2017 19:22
@EriktheOutgolfer Yes. Interestingly, J is much more rank-oriented than APL, but does have that operator.
TIOBot logging off!
@Adám You previously spoke about defining operators. How would I define ¨ if it didn't already exist?
TIOBot should be up in a little bit, patience.
@SocraticPhoenix Thank you so much, it was a great help!
Nov 1, 2017 19:23
¨ isn't quite an operator is it? It's a function modifier?
@H.PWiz You can query the arguments' depth, and recurse if necessary.
@barrycarter um isn't that what an operator is
@EriktheOutgolfer I thought an operator took two values and combined them?
@barrycarter In APL lingo, an operator is a function modifier; a higher-order function.
@barrycarter No, that's a function in APL lingo.
Ah, so ¨ is a monadic operator that happens to operate on functions?
Nov 1, 2017 19:24
all operators operate on functions
@barrycarter Correct.
What about 2 + 3?
@EriktheOutgolfer But operators can also take arrays as operands.
@barrycarter That's an APL function.
OK, is monadic - (minus sign) a function or an operator?
@barrycarter A function.
Nov 1, 2017 19:25
a function; an operator is a function modifier
Oh, OK, so not exactly the common mathematical usage.
Is composition an operator then?
In fact, you can have a monadic operator which takes an array as operand, and derives a monadic function. It will have an appearance very similar to a dyadic function.
@barrycarter Yes.
Is the monadic function f(n) = nth element of array?
@barrycarter "operator" as in "Heaviside operator"
@barrycarter What?
Ignore that.
So you can ¨an array?
Nov 1, 2017 19:28
6 messages moved to Trash
@barrycarter No, but not out of principle, only because we have not defined that (yet - I have an idea).
there we go, TIOBot is back :)
Got it. Some operators can also be applied to arrays, not just functions?
Nov 1, 2017 19:28
#TIO run apl-dyalog ⎕←'Hello, World!'
@Adám
Hello, World!
@barrycarter Yes, in fact, some operators can only take arrays as at least one of their operands.
@barrycarter We can do such an operator now.
You may have noticed when I briefly mentioned that * is power in APL. 5*2 is 25.
* is the power function.
is the power operator.
(In a proper font, they are supposed to have identical stars)
f⍣n applies the function f n times.
#TIO run apl-dyalog ⎕←2×3
@Adám
6
#TIO run apl-dyalog ⎕←2×2×3
@Adám
12
Nov 1, 2017 19:32
#TIO run apl-dyalog ⎕←2×2×2×3
@Adám
24
#TIO run apl-dyalog ⎕←2(×⍣3)3
indeed.
Well, it is supposed to give 24.
Nov 1, 2017 19:33
So the ×⍣3 applies to the 2?
I.e. it did the multiplication 3 times. We need parentheses here to separate the two 3s.
TIOBot logged in!
#TIO run apl-dyalog ⎕←2(×⍣3)3
@Thomas Ward
24
@barrycarter No, it applies between 2 and 3.
Nov 1, 2017 19:33
@Adám oh so dyadic use of just uses the left arg on each iteration. I confuse that a lot
Wouldn't that be "2 x x x 3" or something?
@dzaima Yes. ⍺ (f⍣n) ⍵ is defined as `(⍺∘f⍣n) ⍵
@barrycarter No, because that would be applying one function all the first times, and an entirely different function the last time.
OK, so f ⍣3 applies f to its left arg thrice? as f(f(f(x,x),x,x) or something?
(all the first: monadic; the last: dyadic)
@barrycarter No, to its right. ⍺ (f⍣3) ⍵ is ⍺ f ⍺ f ⍺ f ⍵
@dzaima Operators are never ambivalent. Their derived functions can be, but they are either monadic or dyadic. is dyadic. / and ¨ are monadic.
OK, I'm lost because I don't know what f ⍺ f ⍺ f ⍵ means
Nov 1, 2017 19:38
it's right-associative
@barrycarter it's identical to ⍺ f (⍺ f (⍺ f ⍵))
So, in our case its "2 x 2 x 2 x 3"
@barrycarter Yes.
I think I got it
Nov 1, 2017 19:39
There you have it, an operator which takes an array operand.
Wait, in our example, we applied ⍣3 to the multiplication operator, right?
can also take a function right operand, f⍣g. In that case n is not predetermined, but it will keep applying ⍺∘funtil (⍺ f ⍵) g ⍵.
@barrycarter Yes, but can be applied to any monadic or dyadic function.
@barrycarter multiplication function
@dzaima Yes, function.
So you're saying the result of f⍣3 was the operator that took arrays as operands?
Nov 1, 2017 19:42
@barrycarter No the result of f⍣3 is a new function which takes arrays as arguments
functions take arguments. operators take operands.
OK, so where did we see the operator that takes an array operand? Was "3" the array operand?
@barrycarter Yes.
Ah, got it.
So f⍣= is the fixpoint of f.
#TIO run apl-dyalog ⎕←0.5×⍣=1
@Adám
0
Nov 1, 2017 19:44
If you keep halving 1 you end up with 0.
@Adám isn't = equality comparison?
@EriktheOutgolfer Yes. So?
Two character operators parse before single character ones?
@Adám might be worth mentioning why, first time I saw that I was very confused
0.5×⍣= means keep multiplying 0.5 with the argument until it stops changing.
@barrycarter There are no two-character operators (or functions). This was taking = as right operand.
Nov 1, 2017 19:45
Oh.
@Adám unless you define one yourself
Wait, can ⍣ take "<" as a right operand? Repeat until next result is less than previous result?
@EriktheOutgolfer Yes, userdefined names can be long, but they are only made of alphanumerics.
@barrycarter Yes. can take any dyadic function as right operand.
And any monadic function as a left operand?
Nov 1, 2017 19:47
In fact, sometimes I do most of the work in the right operand, with a trivial left operand.
@barrycarter Or dyadic.
#TIO run apl-dyalog ⎕←cos(x)⍣=1
@barrycarter
line(1,0) : error AC0505: error (VALUE ERROR) executing line "⎕←cos(x)⍣=1"
                                                              ^
Complete: 1 error.
DOMAIN ERROR: There were errors processing the script
 '#'⎕NS ⎕FIX'file:///home/runner/.bin.tio.dyalog'
∧

Real time: 0.030 s
User time: 0.009 s
Sys. time: 0.016 s
CPU share: 85.01 %
Exit code: 0
@barrycarter cos is 2○
#TIO run apl-dyalog ⎕←2○(x)⍣=1
@barrycarter
line(1,0) : error AC0505: error (VALUE ERROR) executing line "⎕←2○(x)⍣=1"
                                                              ^
Complete: 1 error.
DOMAIN ERROR: There were errors processing the script
 '#'⎕NS ⎕FIX'file:///home/runner/.bin.tio.dyalog'
∧

Real time: 0.024 s
User time: 0.005 s
Sys. time: 0.017 s
CPU share: 87.37 %
Exit code: 0
Nov 1, 2017 19:49
@barrycarter Just 2○ no parens needed.
#TIO run apl-dyalog ⎕←2○x⍣=1
@barrycarter
line(1,0) : error AC0505: error (VALUE ERROR) executing line "⎕←2○x⍣=1"
                                                              ^
Complete: 1 error.
DOMAIN ERROR: There were errors processing the script
 '#'⎕NS ⎕FIX'file:///home/runner/.bin.tio.dyalog'
∧

Real time: 0.028 s
User time: 0.006 s
Sys. time: 0.018 s
CPU share: 87.48 %
Exit code: 0
Oh wait
@barrycarter No x either.
I don't need an argument do I
#TIO run apl-dyalog ⎕←2○⍣=1
Nov 1, 2017 19:49
@barrycarter
0.7390851332
is just another normal scalar primitive function.
APL has no reserved words whatsoever. None. Period. All built-ins have non-alphanumeric names.
Hmmm... so 2○ is cosine, what's ○ ?
@barrycarter Pi times.
Ah, so no relation between ○ and 2○?
@barrycarter Yes, both relate to the unit circle, hence the symbol.
Nov 1, 2017 19:52
Ah, but cosine is 2○ just because. I assume 3○ is sine or something?
Naturally, 1○ is sin and 3○ is tan.
Of course
and ¯1○ is arcsin, and so on.
btw @Adám I'd have preferred an operator instead of dyadic
@EriktheOutgolfer But operators are not scalar. 1 2 3○ is the sin,cos,tan.
Nov 1, 2017 19:54
What is composition?
@barrycarter
Say I wanted sin(tan(x)) ?
Ah.
@barrycarter ○/1 3 x
Is there an operator to flip the arguments of a function?
@H.PWiz Yes, I was just getting to that one actually.
Nov 1, 2017 19:55
Great
is a monadic operator taking a dyadic function and deriving an ambivalent function.
⍺ f⍨ ⍵ is ⍵ f ⍺
@Adám This applies ○ to 1 3 and x?
f⍨ ⍵ is ⍵ f ⍵
@barrycarter This is a reduction, so ○/1 3 x is 1○3○x and since APL functions are right-associative, this is 1○(3○x) i.e. sin(tan(x))
@EriktheOutgolfer You see why shouldn't be an operator?
So, x here is actually "x", not the times function?
@Adám hmm
yes
Nov 1, 2017 19:58
@EriktheOutgolfer If you want the derived function ("1○" had been an operator), just do sin←1∘○
@barrycarter Yes.
@barrycarter If you want an actual function which is the composition of sin and tan, do 1○3○⊢ or 1○3∘○
( is the identity function)
So, ○ isn't an operator? It seems to take an array (scalar) as its sole operand and returns a function?
no it isn't
not only operators take arrays :p
@barrycarter No, it is a function. It pairs up. 1 2 3○a b c is sin(a),cos(b),tan(c)
So it's a function that takes a scalar as an argument and returns a function?
@EriktheOutgolfer Right, we saw that can take an array too.
@barrycarter No, it doesn't return a function. It is the circular function. Its left argument is restricted to integers in the range ¯12 to 12.
@H.PWiz Was clear?
Nov 1, 2017 20:02
Yes, I would say so
But it still returns the function sine, for example, right? Input: 1, output: sin() as function?
it doesn't
it just does sin
Right, the pure sine function?
@barrycarter It doesn't return it. It calculates the sine when the left arg is 1. To get a "sine" function, you'd have to compose a fixed left argument of 1 with the function as follows: sin← 1∘○
seems very simple, but it has some neat applications.
Monadic +⍨ is double. Monadic ×⍨ is square.
Oh, so n○x is either sin(x), cos(x), or tan(x) depending on n. Think I got it.
Nov 1, 2017 20:04
not just those three
#TIO run apl-dyalog ⎕←,⍨/1 2 3 4 5
@barrycarter if it did, then (1○)3 would work, but it doesn't - in instantly needs both sides or has to be left untouched, by composing
Right. There's also some arc stuff with _1 or something
@H.PWiz
 5 4 3 2 1
@barrycarter Yes, and a whole host of other functions to. 25 to be precise.
I (informally) call "selfie" when the derived function is used monadically, because that's what it does, and it looks like a selfie (photo) too.
Nov 1, 2017 20:06
OK, I'm off, but thanks @Adám -- this was interesting (will lurk starting now)
@H.PWiz Yes, but you can also just use monadic .
@Adám Yes, I know. Just thought it was cool
Yeah, we've gone over time. Thank you to all participants! Next week?
 
Conversation ended Nov 1, 2017 at 20:07.