« first day (1055 days earlier)      last day (1600 days later) » 

9:00 PM
You can indeed, or even better, the numbers
 
oh yeah
 
Go for it!
 
wait is it ∊
to check if something is in something else
I forgot
 
Yes.
 
⎕←{⍵∊∘.×⍨1↓⍳⍵}13 14
 
9:01 PM
@EdgyNerd
0 0
 
@EdgyNerd Uh oh, you still need a ⍳⌈/⍵ instead of ⍳⍵
 
oh yeah
⎕←{⍵∊∘.×⍨1↓⍳⌈/⍵}13 14
 
@EdgyNerd
0 1
 
:D
 
Bravo!
Pretty cool, eh?
 
9:02 PM
yeah
 
Brain is mush, or do you want more?
 
so basically, APL is shortest if you (ab)use the fact that it's really good for arrays / multi-dimensional array
@Adám sure I can do some more
 
Absolutely, but it certainly isn't abuse. APL is terrible if you ignore its array handling capabilities. In fact, some say APL should mean "Array Processing Language".
 
does it have an 'official' thing that it stands for?
 
A Programming Language ⍨
 
9:04 PM
A Programming Language
 
probably the best acronym there is tbh
 
oh wow
 
Remember that I told you APL was intended as a better alternative to TMN?
 
yeah
 
⎕←{2=⍴⍸⍵⍷∘.×⍨⍳⍵} 97 ⊣ 'I think weirdly.'
 
9:05 PM
@Quintec
1
 
⎕←⍸{⍵∊∘.×⍨1↓⍳⌈/⍵}⍳100
 
@EdgyNerd
4 6 8 9 10 12 14 15 16 18 20 21 22 24 25 26 27 28 30 32 33 34 35 36 38 39 40 42 44 45 46 48 49 50 51 52 54 55 56 57 58 60 62 63 64 65 66 68 69 70 72 74 75 76 77 78 80 81 82 84 85 86 87 88 90 91 92 93 94 95 96 98 99 100
 
oh wait
why does that get non-primes?
 
APL was created by a mathematician — to replace TMN. Only later came the idea to make a programming language out of it. He presented the idea in a book called A Programming Language and when they went to implement it, they used the acronym…
 
oh wow
 
9:07 PM
⍞←{⍵∊∘.×⍨1↓⍳⌈/⍵}⍳10
 
@Adám 0 0 0 1 0 1 0 1 1 1
 
oh right
is there a NOT builtin in APL?
 
@EdgyNerd ~
 
⎕←⍸~/{⍵∊∘.×⍨1↓⍳⌈/⍵}⍳100
 
@EdgyNerd
DOMAIN ERROR
 
9:08 PM
⎕←⍸~{⍵∊∘.×⍨1↓⍳⌈/⍵}⍳100
 
@EdgyNerd
1 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
 
Hold on, NOT is a monadic function.
 
oh yeah
 
But wait, we can do better.
Remember that primes are all the numbers NOT in the multiplication table?
 
oh yeah
 
9:09 PM
So if we have all the numbers and just remove those that are in the multiplication table, that leaves the primes.
 
⎕←⍸{⍵~∊∘.×⍨1↓⍳⌈/⍵}⍳100
 
Look at this:
 
@EdgyNerd
DOMAIN ERROR
 
⍞←'mississippi'~'ps'
 
@Adám miiii
 
9:10 PM
Dyadic ~ is "set subtraction" a.k.a. "without"
 
so use ~ instead of ∊?
 
@EdgyNerd Yes.
 
⎕←⍸{⍵~∘.×⍨1↓⍳⌈/⍵}⍳100
 
@EdgyNerd
DOMAIN ERROR
 
And remove the
 
9:11 PM
⎕←{⍵~∘.×⍨1↓⍳⌈/⍵}⍳100
 
@EdgyNerd
1 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
 
I'm kinda confused how that works
 
You're kind of doing double work here. Let's take it step by step. We start with all the integers above 1:
⍞←1↓⍳10
 
@Adám 2 3 4 5 6 7 8 9 10
 
Then we make a times table for them:
⎕←{∘.×⍨1↓⍳⍵}10
 
9:12 PM
@Adám
 4  6  8 10 12 14 16 18  20
 6  9 12 15 18 21 24 27  30
 8 12 16 20 24 28 32 36  40
10 15 20 25 30 35 40 45  50
12 18 24 30 36 42 48 54  60
14 21 28 35 42 49 56 63  70
16 24 32 40 48 56 64 72  80
18 27 36 45 54 63 72 81  90
20 30 40 50 60 70 80 90 100
 
And remove the times table from the numbers:
⍞←{(1↓⍳⍵)~∘.×⍨1↓⍳⍵}10
 
@Adám 2 3 5 7
 
Now we can "break out the 1↓⍳⍵ phrase:
⍞←{{⍵~∘.×⍨⍵}1↓⍳⍵}10
 
@Adám 2 3 5 7
 
we could also use an inline variable assignment:
⍞←{c~∘.×⍨c←1↓⍳⍵}100
 
9:14 PM
@Adám 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
 
@EdgyNerd Understand?
 
kind of
~ confuses me a little still
 
@EdgyNerd It takes a list on the lift and removes all the elements that appear anywhere in the array on the right.
 
ohhh right
I thought it was the other way round
that's why I was confused
 
Think of it like - it takes something on the left and removes what's on the right.
 
9:16 PM
yeah
 
Okay, after watching the video on thunks: Is Marshall a literal wizard? Like, with wands and ravens and such?
 
@voidhawk Yes.
 
Yeah, I thought so
 
⍞←{c~∘.×⍨c←1↓⍳⍵}1000
 
@EdgyNerd 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293 307 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499 503 509 521 523 541 547 557 563 569 571 577 587 593 599 601 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691 701 709 719 727
733 739 743 751 757 761 769 773 787 797 809 811 821 823 827 829 839 853 857 859 863 877 881 883 887 907 911 919 929 937 941 947 953 967 971 977 983 991 997
 
9:17 PM
oh wow it can do that
 
@EdgyNerd Why not? (other than it being a bit odd that it posted two messages)
 
because a 1000x1000 table is big
and it makes a table for the numbers from 1-1000
 
array processing language, remember?
 
yeah
 
Each number needs two bytes, and there are a million of them, so that's about 2MB.
 
9:19 PM
oh wow
 
The bot handles arrays up to 128MB, if I recall correctly.
 
what's next?
 
But on an actual installed APL system, there's no limit. We regularly test arrays up to about 100GB. Though you can go bigger if you have the money for that kind of RAM.
@EdgyNerd You can build your vocabulary by yourself, so let's instead advance your knowledge of those functions.
 
@Adám how fast can it do arrays that large?
 
9:22 PM
@EdgyNerd Depends on the operation. For a lot of arithmetic and comparison, the bottleneck is actually the speed at which the RAM can deliver data to the CPU, while the CPU is just sitting semi-idle, waiting for more work.
 
oh wow
also I just noticed you can hover over stuff in the symbol shortcut thing to see what they do
that's quite useful
⍞←○100
 
@EdgyNerd 314.1592654
 
We haven't even gotten to those functions yet, but there are things where Dyalog APL beats carefully hand-crafted C, which is of course a paradox since Dyalog APL is written in C…
@EdgyNerd So, in a dfn (those functions written in braces) you can actually have multiple statements:
⍞←{c←1↓⍳⍵ ⋄ c~∘.×⍨c}10
 
@Adám 2 3 5 7
 
how does that work?
 
9:26 PM
You've already met as a statement separator. Works the same here.
 
does it return the result of the last statement?
 
No, it returns the first non-assignment.
 
oh right, I was trying to read it from far right to left
instead of the right of the first statement
 
@EdgyNerd Yeah, you can write like that as well, but not using :
⍞←{c~∘.×⍨c ⊣ c←1↓⍳⍵}10
 
@Adám 2 3 5 7
 
9:27 PM
is actually just a very very simple function (so simple that people have a hard time with it). It takes two arguments and returns the left:
⍞←3⊣4
 
@Adám 3
 
oh wow
does ⊢ return the right by any chance
 
It does :-)
So what's actually happening in …c ⊣ c←… is that we assign to c then discard that in favour of c
 
unfortunately apl is not a 2d language so ⊤ and ⊥ do not return below and above
 
Nope. Sorry. But there's actually a way you can almost do that.
 
9:29 PM
what is modulo in APL?
 
| but with swapped arguments compared to ÷
 
so 5|2 is 1?
or is it 2|5
 
Of course, you can just use whenever the order of arguments doesn't suit you.
 
⎕←5|2
 
@frank
2
 
9:30 PM
⎕←2|5
 
@frank
1
 
@Adám Do you know if the Dyalog interpreter is written in "Whitney C" or is it more standard?
 
⍞←{⍵|⍨×⍨!⍵-1}13
 
@EdgyNerd 0
 
@voidhawk Very much a standard looking, actually quite old-fashioned, C.
 
9:31 PM
⍞←{⍵|⍨×⍨!⍵-1}14
⍞←{⍵|⍨×⍨!⍵-1}13 14
 
@EdgyNerd 0 0
 
oh that didn't work
 
What are you trying to do?
 
I was trying to do wilson's theorum (which I saw in this answer) in APL
 
w-1 factorial squared modulo w?
 
9:32 PM
The x mod square of the beta function beta function of x?
 
⍞←{⍵|×⍨!⍵-1}13 14
 
@EdgyNerd 0 0
 
That's "correct", but I'm not sure what it means.
 
it should give 1 if it's prime I'm pretty sure
 
@EdgyNerd Really? Never heard of that. But then again, I am not a mathematician.
 
9:34 PM
actually I don't think that works nvm
 
Anyway, continuing with dfns: You can set up guards, which are conditional expressions followed by : followed by an expression which will give the result if the conditional was true. If it isn't, the dfn continues with the next statement:
⍞←{⍵>10:'big' ⋄ 'small'}15
 
@Adám big
 
⍞←{⍵>10:'big' ⋄ 'small'}7
 
@Adám small
 
does that require the ⋄?
 
9:36 PM
Yes, otherwise there's no way to see where the guard result ends.
And you can't use either, for obvious reasons if you think about it.
 
yeah
what other (basic) conditionals are there?
 
You can catch errors with an error number followed by :: followed by the result-if-error. Each error type (DOMAIN, LENGTH, etc.) has its own code. DOMAIN ERROR is number 11.
⍞←{11:'nope' ⋄ ÷0}0
 
@Adám DOMAIN ERROR
 
Oops.
⍞←{11::'nope' ⋄ ÷0}0
 
@Adám nope
 
9:39 PM
⍞←{11::'nope' ⋄ ÷0}10
@DyalogAPL Pretty please?
⍞←{11::'nope' ⋄ ÷0}10
 
@Adám nope
 
@DyalogAPL Thank you, that's very kind.
 
so it runs the right statement and if it errors with the error code it returns the left argument
 
@EdgyNerd Not exactly. All -separated statements are evaluated in order from left to right. Error guards are "set up" and execution jumps back to the nearest error guard of the appropriate type whenever such an error happens after the guard has been set up.
 
⎕←{c>10: }
oops
 
9:41 PM
@frank
{c>10:}
 
:} Cute.
 
⎕←{c←⍵ ⋄ c>10: 'test' ⋄ c←11 ⋄ 'testing'} 9
 
@frank
testing
 
Ah, the scientist in action. Right, normal guards don't jump into action if the condition becomes true later.
@EdgyNerd That's actually it for dfns. There's another functional form (call tradfns) which allows all the traditional control structures, but it is also less elegant.
However, dfns have one more trick up their sleeve. Anonymous recursion. Are you up for it?
 
sure (although I will have to go in around 15 mins so that might be a problem)
 
9:46 PM
We can always start and continue another time.
 
ok
 
Inside a dfn, means the dfn itself. So e.g. we can define the factorial (in TMN) as:
f(x)={1         if x=1
      x×f(x-1)  otherwise
As a dfn: {⍵=1:1 ⋄ ⍵×∇⍵-1}
⍞←{⍵=1:1 ⋄ ⍵×∇⍵-1}4
 
@Adám 24
 
⍞←{⍵=0: ⍵×∇⍵-1 ⋄ 1}5
 
@EdgyNerd 1
 
9:49 PM
oh wait
why doesn't my one work?
 
@EdgyNerd It says: if the argument is 0, recurse with that formula, else return 1. 5≠0, so it gives 1.
 
oh right
⍞←{⍵≠0: ⍵×∇⍵-1 ⋄ 1}
 
@EdgyNerd      ∇{⍵≠0:⍵×∇ ⍵-1 ⋄ 1}
 
⍞←{⍵≠0: ⍵×∇⍵-1 ⋄ 1}5
 
@EdgyNerd 120
 
9:51 PM
:D
 
Yup
Are you familiar with Fibonacci numbers?
 
yep
 
Can you write the Fib function?
 
{⍵ ∇ ⍵ + ⍺}
⍞←0{⍵ ∇ ⍵ + ⍺}1
 
@EdgyNerd DOMAIN ERROR
 
9:54 PM
@Adám what will the Fib function do?
 
@EdgyNerd If the argument is less than or equal to 1 it gives 1, else it gives (Fib ⍵-1)+(Fib ⍵-2)
 
so the nth Fibonacci number
 
Yeah.
 
⍞←{⍵>1: ∇⍵-1+∇w-2⋄1}5
 
@EdgyNerd VALUE ERROR
 
9:57 PM
⍞←{⍵>1: (∇⍵-1)+∇w-2⋄1}5
 
@EdgyNerd VALUE ERROR
 
@EdgyNerd You have a double-yoo instead of an omega.
 
⍞←{⍵>1: (∇⍵-1)+∇⍵-2⋄1}5
 
@EdgyNerd 8
 
oh ok
 
9:58 PM
Btw, a real full APL system would tell you much more:
      {⍵>1:(∇ ⍵-1)+∇ w-2 ⋄ 1}5
VALUE ERROR: Undefined name: w
      {⍵>1:(∇ ⍵-1)+∇ w-2 ⋄ 1}5
                     ∧
 
oh ok
 
@EdgyNerd That's very good. You're a quick learner.
You have to go, no?
 
yeah basically
 
OK, it was fun. Have a look at these lessons to build your APL vocabulary. And never hesitate to pop in and ask.
 
ok
I'll continue tomorrow I guess
 
10:01 PM
Sure. I should be around from 9 AM UTC or so.
 
⎕←{⌽{⍵>1: 1 ⋄ (∇⍵-1)+∇⍵-1}⍳⍵}5
 
@frank
LENGTH ERROR
 
⎕←{⌽{⍵>1: (∇⍵-1)+∇⍵-1 ⋄ 1}⍳⍵}5
 
@frank
LENGTH ERROR
 
@frank The condition is (⍳5)>1 which is neither 0 nor 1 so it is invalid.
What you probably want is to apply the function to each element of ⍳5, no?
 
10:07 PM
⎕←{⌽{⍵>1: (∇⍵-1)+∇⍵-1 ⋄ 1}¨⍳⍵}5
 
@frank
16 8 4 2 1
 
oh I see my mistake
 
Should one of your -1 be -2?
 
⎕←{{⍵>1: (∇⍵-1)+∇⍵-2 ⋄ 1}¨⍳⍵}5
 
@frank
1 2 3 5 8
 
10:08 PM
alright
so I assume ∇ looks at the function its currently in?
 
This is of course a horribly inefficient way to create Fibonacci numbers.
@frank That's correct. If you want to call another function, you can use its name or pass it in as an operand.
 
yes I imagine creating fibonacci numbers backwards isnt the best way to do it haha
 
What you can do instead is iterate over a beginning pair, adding one more element, and then continuing with the last two elements.
 
how would you keep track of where you are in the sequence?
 
⍞←{⍵,+/¯2↑⍵}1 1 2 3
 
10:11 PM
@Adám 1 1 2 3 5
 
@frank I don't understand. You don't need to, do you?
 
if you wanted to get the first 10 fibonacci numbers, for example
 
You could have a condition on the length, and quit if long enough.
You could recurse and keep passing in the target length as the other argument.
Alternatively, you could apply the function N times. Do you know about ?
 
ah yes, I saw that when I looked at the bookmarked lesson
 
So you know how TMN writes f³(x) meaning f(f(f(x)))?
So that's a very different ³ than in x³.
We write x³ as x*3 and f³ as f⍣3:
⍞←{⍵,+/¯2↑⍵}⍣10,1
 
10:16 PM
@Adám 1 1 2 3 5 8 13 21 34 55 89
 
⍞←10⍣⍨{⍵,+/¯2↑⍵}1
 
@frank SYNTAX ERROR
 
ah oh well
 
is not a function but rather an operator, so can't swap its operands.
Recursive version:
 
makes sense
 
10:18 PM
⍞←10{⍺=≢⍵:⍵ ⋄ ⍺∇⍵,+/¯2↑⍵}1
 
I just thought the comma make it look a bit confusing
 
@Adám 1 1 2 3 5 8 13 21 34 55
 
makes sense
 
@frank It isn't actually needed, but something has to separate the 10 from the 1. would do the trick, but since we're really dealing with a vector, I thought I'd initialise the right argument as a vector.
You can also use a parenthesis:
⍞←({⍵,+/¯2↑⍵}⍣10)1
 
@Adám 1 1 2 3 5 8 13 21 34 55 89
 
10:19 PM
Or simply give it a name:
⋄ Fib10←{⍵,+/¯2↑⍵}⍣10 ⋄ ⎕←Fib10 1
 
@Adám
1 1 2 3 5 8 13 21 34 55 89
 
Or you could wrap it in another dfn:
⍞←{{⍵,+/¯2↑⍵}⍣⍵⊢1}10
 
@Adám 1 1 2 3 5 8 13 21 34 55 89
 
is there a way to get the ⍵ of another function?
if that makes sense
 
@frank Of an outer function?
 
10:21 PM
I guess you could pass it into the inner function as ⍺ or something
yeah
 
Indeed. That's the best way. Alternatively, you can give that a name in the outer function and the inner function will be able to "see" that name.
 
10:35 PM
is there a sort builtin? I know ⍋returns indices in ascending order
but do I have to do e.g. ⍵[⍋⍵] to sort?
 
@frank No. I'm trying to push for one, or at least a better way to sort, but for now you have to do that or {(⊂⍋⍵)⌷⍵} or (⊂∘⍋⌷⊢).
If you're golfing, you can use my experimental "Extended Dyalog APL" which does have sort functions; monadic and .
 
11:32 PM
@Adám In that case, I'd guess a single dyadic "sort-by" would work in most use cases
 
@Bubbler Our CTO has suggested removing the current dyadic functionality and making dyadic sort-by like in J. I really don't like removing backwards compatibility, and I find dyadic pretty cool when it is what I need.
 
Then plain sort is f⍨ and sort-by-key is key f ⊢
though yeah, replacing feels like too much of a breaking change
 
Yes. But I instead propose "sane indexing" (alternative names: select, reorder, permute) which is simply ⌷⍤0 99. This allows sort to be ⍋⊇⊢ and sort-by key is data⊇⍨∘⍋key.
I'd actually also really like to see "reverse compose" f⍛g (alt.: against, before) which is (f ⍺)g ⍵ and then allows key⍋⍛⊇data for ⍋⍛⊇⍨data.
 
I don't really think I had a chance to use current dyadic by the way
 
Same, never used but I don't do a lot of string processing
 
11:48 PM
Occasionally, it comes up in a code golf where it secures a win. Other than that, it can be used to do various human language sorts. Here are some examples.
 
@Bubbler The only time I've used it is ⍬⍋ codegolf.stackexchange.com/a/169490/71256
 
Hm, how do I search for all my answers that contain ?
@H.PWiz That's just a golfing tip rather than actual usage of its power.
 
The main problem is that it only works with char arrays
 
Yeah. When we designed the TAO, we played around with extending too, but rolled it back as we couldn't figure out a consistent extension.
 
What does TAO stand for?
 
11:58 PM
Try at online?
 
Total Array Ordering. A system of axioms that allows any two basic arrays to be compared. (Basic here means has no refs).
E.g. how should 2 3⍴4 sort compared to 3 2⍴4, and how about vs ''?
 

« first day (1055 days earlier)      last day (1600 days later) »