« first day (515 days earlier)      last day (2132 days later) » 

8:25 AM
@Adám Sorry I just got home from family lunch
And I think it's relatively early in the UK
 
8:56 AM
@Sherlock9 10 am.
 
Ah
If you have time to do a lesson now, I'm ready when you are
It's okay if you don't. I'll start going through the bookmarked lessons
 
@Sherlock9 I'll try a little. (I actually don't work on Sundays, but teaching APL is just too much fun to pass up, and children are in school.)
 
Oh I see. I'll keep that in mind in the future
 
So, you've already met a few operators. / etc.
And you've learned how you can add your own functions as dfns. {⍺+⍵÷2}
 
Yep
 
9:10 AM
So too can you add your own operators. The syntax for the operator equivalent of a dfn, "dop", is identical to the dfn, except it must contain ⍺⍺ somewhere. And if you want the operator to be dyadic like and , it must contain ⍵⍵. APL will scan your code and assign the correct type depending on that.
 
Okay, why ⍺⍺ first?
 
E.g. to make an operator that takes two functions f and g and derives the function ⍺ f ⍵ g 2 you'd write MyOp←{⍺ ⍺⍺ ⍵ ⍵⍵ 2}. So ⍺⍺ is the left operand and ⍵⍵ is the right operand, while (optional) and are arguments just like in dfns.
@Sherlock9 Because a monadic operator, like / only has a left operand: +/
 
Ohh
 
@Sherlock9 So a cover operator for / when deriving a monadic function would be Slash←{⍺⍺/⍵}
 
So if I wanted to remake . for inner product, I'd use {⍺ ⍺⍺/⍵⍵ ⍵}
I think
 
9:14 AM
@Sherlock9 Yes, but a ., not a /
 
{⍺ ⍺⍺/ ⍵⍵ ⍵} may be clearer
Oh
 
@Sherlock9 Or {⍺⍺/ ⍺ ⍵⍵ ⍵}, but only for scalars and vectors.
 
What's a cover operator, actually?
@Adám Ah yes, that's what I meant
I suppose matrices would be tougher
 
@Sherlock9 Just a user-defined name that behaves like the built-in. Not very useful ;-)
 
How would you write an operator that takes a function, an array with rank ≥ 3, and a scalar representing which rank you want the operator to function on?
 
9:17 AM
@Sherlock9 Yes, but still better than coding it in C or something. In fact. Quite a few of our "tougher" built-ins are written in APL!
 
@Adám Haha
Write more builtins in APL until it's APL all the way down
Even the bits :P
Actually is there typing in APL, dynamic or static? Like ⍵ must be an array and ⍺ must be a function?
 
@Sherlock9 The "signature" would be (fn MyRankOp rank)array, so you'd use ⍺⍺ and ⍵⍵ and . Or you could use rank fn MyRankOp array by using and ⍺⍺ and .
@Sherlock9 No, either can be either. But a function cannot take a function as argument, so the only way to make a function is by making it so from inside your code.
@Sherlock9 And therefore, can never be a function.
 
Riiiight
I'd need to make it an operator
{⍺⍺ MyOp ⍵} or some such
 
@Sherlock9 Yes, where MyOp is your code. To name it, you'd do MyOp←{… as always.
Sometimes, you can use an operator just as a convenient way to have a "function" take 3 or 4 arguments.
 
Do you have an example?
 
9:26 AM
@Sherlock9 E.g. a Pythagorean checker: Right←{(⍵*2)=(⍺⍺*2)+(⍵⍵*2)} which you can call with (3 Right 4)5 or 3 Right 4⊢5.
 
How does 4⊢5 not return 5 at the end of 3 Right 4⊢5?
 
@Sherlock9 Because operators bind their operands stronger than functions bind their arguments.
Here is a quiz for you: What is the difference between a dyadic function, e.g. {⍺+⍵}, and monadic operator deriving a monadic function, e.g. {⍺⍺+⍵}?
 
How tightly they bind their arguments?
 
@Sherlock9 Yes, but you won't really see any difference when it comes to the left operand/argument. What else?
 
The left operand can be a function?
 
9:33 AM
@Sherlock9 Sure, but then we couldn't compare the two if we were not talking about using an array left argument/operand.
Let me show you with an experiment:
 
Sure
 
⎕←2 3 4{⍺+⍵}10 20 30 ⋄ ⎕←2 3 4{⍺⍺+⍵}10 20 30
 
@Adám
12 23 34
12 23 34
 
So far they are identical.
⎕←2 3 4{⍺+⍵}¨10 20 30 ⋄ 2 3 4{⍺⍺+⍵}¨10 20 30
 
@Adám
12 23 34
 
9:35 AM
Oops:
⎕←2 3 4{⍺+⍵}¨10 20 30 ⋄ ⎕←2 3 4{⍺⍺+⍵}¨10 20 30
 
@Adám
12 23 34
┌────────┬────────┬────────┐
│12 13 14│22 23 24│32 33 34│
└────────┴────────┴────────┘
 
@Sherlock9 You understand why ^?
 
Huh
Well I don't understand how the each operator works
So I could use a hint :D
 
@Sherlock9 Each just applies a function to each (d'oh!) element of it's argument:
⎕←{
 
@Adám
line(1,0) : error AC0505: error (SYNTAX ERROR) executing line "{0::⎕←⊃⎕DM⋄⎕←{}(⎕NS⍬).⍎'⎕CY''salt''⋄⎕SE.UCMD''←box on -f=on -t=tree''⊣enableSALT⋄⍬'"
                                                               ^
Complete: 1 error.
DOMAIN ERROR: There were errors processing the script
 '#'⎕NS ⎕FIX'file:///home/runner/.bin.tio.dyalog'
∧

Real time: 0.037 s
User time: 0.004 s
Sys. time: 0.031 s
CPU share: 96.24 %
Exit code: 0
 
9:38 AM
⎕←{'(',⍺,')'}2 3⍴⎕A
 
@Adám
VALUE ERROR
 
So it takes the left array thrice?
 
⎕←{'(',⍵,')'}2 3⍴⎕A
 
@Adám
(ABC)
(DEF)
 
⎕←{'(',⍺,')'}¨2 3⍴⎕A
 
9:39 AM
@Adám
VALUE ERROR
 
⎕←{'(',⍵,')'}2 3⍴⎕A
 
@Adám
(ABC)
(DEF)
 
Ugh, I'm making a mess today ⍨
⎕←{'(',⍵,')'}¨2 3⍴⎕A
 
@Adám
┌───┬───┬───┐
│(A)│(B)│(C)│
├───┼───┼───┤
│(D)│(E)│(F)│
└───┴───┴───┘
 
Huh
 
9:41 AM
@Sherlock9 Not exactly. 2 3 4{⍺⍺+⍵} derives a new stand-alone monadic function which in turn is applied to each of 20 and 30 and 40.
 
{⍵}¨2 3⍴⎕A
 
@Sherlock9 Need ⎕←
 
⍞←{⍵}¨2 3⍴⎕A
 
@Sherlock9 ABC
 
Oh right
⎕←{⍵}¨2 3⍴⎕A
 
9:43 AM
@Sherlock9
ABC
DEF
 
@DyalogAPL You can't really tell, as {⍵} (which is the same as ) is a no-op.
 
I was hoping for the boxes with one letter each in them
@Adám Oh I see
 
@Sherlock9 Ah, but a simple scalar won't let itself be enclosed:
⎕←{⊂1/⍵}2 3⍴⎕A
 
⎕←{,⍵}¨2 3⍴⎕A
 
@Adám
┌───┐
│ABC│
│DEF│
└───┘
@Probie
┌─┬─┬─┐
│A│B│C│
├─┼─┼─┤
│D│E│F│
└─┴─┴─┘
 
9:44 AM
So how would you write the difference the between a dyadic function and a monadic operator that derives a monadic function?
 
⎕←{⊂1/⍵}¨2 3⍴⎕A
 
@Adám
┌───┬───┬───┐
│┌─┐│┌─┐│┌─┐│
││A│││B│││C││
│└─┘│└─┘│└─┘│
├───┼───┼───┤
│┌─┐│┌─┐│┌─┐│
││D│││E│││F││
│└─┘│└─┘│└─┘│
└───┴───┴───┘
 
@Sherlock9 The former is a dyadic function, the latter derives a monadic function. :-)
 
:-) ⍨
 
10:08 AM
@Adám I have a question about the APL license application
I have a Windows system and a Mac OS X system
Do I really need to apply once for each system?
 
@Sherlock9 No, it is enough to drop an email to sales@.
 
Alright, thanks
 
 
1 hour later…
11:17 AM
Given a (hopefully aligned) array of bools which has a length which is a (small) multiple of my machine word size, how can I perform an efficient bit shift? I've currently got two ideas which I plan to benchmark against each other ("drop then take" and "rotate and mask") but does anyone have any other ways of doing it (hopefully that Dyalog will translate into my machine's bitshift operation in the case where the array is machine word sized)?
 
@Probie I think rotate and mask is the way to go, but you can also try expand and take. Do you know how to compare performance?
 
@Adám I found a function for it a few weeks back, but I can't remember the name. cmpx or something
 
@Probie Yes, you can )copy dfns cmpx or just use the ]runtime -compare "expr1" "expr2" user command.
 
@Adám Last time I tried it, I didn't know how to use )copy properly, so I just found the source and copied it in by hand...
 
@Probie You can always write something and press F1.
@Probie OK, gotta go. Good luck with it, and let me know what you find!
 
11:27 AM
@Adám but I only learnt that about a week ago. Have fun
 
 
1 hour later…
12:44 PM
@Adám On my machine, {64↑⍺↓⍵} is the fastest I can get for a single machine word left shifted, but that operation takes 3 times as long as {⍺⌽⍵} so the bottleneck seems to be masking. since {(⍺⌷masks)∧⍺⌽⍵} takes 30%-50% longer than {64↑⍺↓⍵}.
 
What is the best way to get intermediate values in a reduction? If my vector is ⍳5 and I'm applying the operation +, I want to get ((5), (4 + 5), (3 + (4 + 5)), (2 + (3 + (4 + 5))), (1 + (2 + (3 + (4 + 5))))) as my result. Scans don't work quite as intended here
 
ngn
@Cowsquack +\⌽⍳5
 
@Cowsquack {⍺⍺⍨\⌽⍵}
 
perhaps I shouldn't have used + as an example, instead of + I will have a non-commutative operation
 
ngn
@Probie that one assumes associativity. It returns 5 (4+5) ((3+4)+5) (((2+3)+4)+5) ((((1+2)+3)+4)+5)
 
1:01 PM
@ngn I will take a look into that
as of now I have an external variable to store the progress, to which I append the next value at every iteration of the reduction, so something like z←⍬⋄{⊃z,←⊂⍺f⍵}/vec
actually after I append it to z, I perform an operation on it, so more like z←⍬⋄{g⊃z,←⊂⍺f⍵}/vec
 
1:15 PM
@Cowsquack Is this for golf, or does performance matter?
 
not for golf, performance does matter
 
1:28 PM
my initial approach is faster, but not as elegant Try it online!
 
⎕←-{⌽¨⍺⍺{(⍺ ⍺⍺ ⊃⍵),⍵}/,¨⍵}3 3 3⍴⍳27
 
@Probie
┌────────┬────────┬────────┐
│3 ¯1 2  │6 ¯1 5  │9 ¯1 8  │
├────────┼────────┼────────┤
│12 ¯1 11│15 ¯1 14│18 ¯1 17│
├────────┼────────┼────────┤
│21 ¯1 20│24 ¯1 23│27 ¯1 26│
└────────┴────────┴────────┘
 
⎕←-/3 3 3 ⍴⍳27
 
@Probie
 2  5  8
11 14 17
20 23 26
 
⎕←-{⌽¨⍺⍺{(⍺ ⍺⍺ ⊃⍵),⍵}/,¨⍵}⍳27
 
1:31 PM
@Probie
┌────────────────────────────────────────────────────────────────────────────────────┐
│27 ¯1 26 ¯2 25 ¯3 24 ¯4 23 ¯5 22 ¯6 21 ¯7 20 ¯8 19 ¯9 18 ¯10 17 ¯11 16 ¯12 15 ¯13 14│
└────────────────────────────────────────────────────────────────────────────────────┘
 
No idea how robust that is, but it avoids recalculation
 
I'm going to need some time to understand all that :)
⎕←-/⍳27
 
@Cowsquack
14
 
{⌽¨⍺⍺{(⍺ ⍺⍺ ⊃⍵),⍵}/⊂¨⍵} is probably better. Using ravel to box things is probably not the best idea
 
the performance of f/ and `f` improves drastically when f is a single-function train instead of a dfn
 
1:47 PM
@Cowsquack Probably because Dyalog optimises certain common scans, but if you hide it away in dfn it can't "look inside" and see that it's a case it knows how to optimise
 
makes sense
 
 
1 hour later…
ngn
2:56 PM
@Cowsquack what's the larger problem you're trying to solve? (if you're at liberty to disclose it)
 
 
1 hour later…
4:06 PM
@ngn it's in the student competition, I don't know if I should disclose which problem it is
 
ngn
4:41 PM
@Cowsquack ah, I see. nvm then
 
@Probie Btw, for performance, you generally want to avoid nested or heterogeneous arrays.
 
5:43 PM
⎕←2 2 2⍴4 4⍴⍳8
 
@Sherlock9
1 2
3 4

5 6
7 8
 
Ah it does reshape twice. Interesting :D
 
ngn
@Sherlock9 what did you expect?
 
5:59 PM
codegolf.stackexchange.com/q/5651/41805 seems like a nice little challenge for apl
 
 
2 hours later…
8:25 PM
@ngn Well, I could have gotten some sort of error. A syntax error maybe
 
8:47 PM
@Sherlock9 No, remember, ALL APL functions are treated equal. The leftmost has no influence yet when the rightmost does its thing, and vice versa. x⍴y is not a special syntax for an array — it is just another expression.
 
 
1 hour later…
9:54 PM
@Probie I asked our expert on such matters. Rotate and mask is indeed fastest. (We don't recognise this combination to use native bit-shifting, which I think this is due to bitshifting being a very rare operation for APL needs.) However, if you do have a lot of data, shifting left is fastest by dropping and then indexed assignment. Shifting right may be fastest by constructing the 0s'-prefix and concatenating in-place, then negative dropping.
 

« first day (515 days earlier)      last day (2132 days later) »