« first day (749 days earlier)      last day (2202 days later) » 

09:35
@user8935023 I can get you write access to this room. If you want that, just drop me an email: adam@ with the same domain as www.dyalog.com
10:23
hey all! I wrote this function

normalize←{↑((⍵≥97)∧(⍵≤122)) ((⍵≥65)∧(⍵≤90)) 1/((⍵-96) (⍵-64) 0)}

and I wanted a little bit of help removing some of these parenthesis. I went a little bit overboard to make sure all the precedence was correct.
@Aearnus I don't think I've seen you here before. Welcome. I'll help you with that.
@Adám just got recommended here from twitter!
@Aearnus One of the things you need to get used to in APL is working with arrays. First, will the argument always be a single number (a scalar)?
yeah, the argument will always be a scalar -- I'm feeding it unicode codepoints
@Aearnus OK, so let's have a look at ((⍵-96) (⍵-64) 0). You are essentially subtracting three numbers from , so you can write this as ⍵-96 64 0. Also, it doesn't need any parens at all, as it is right-most, and APL is right-associative.
10:28
@Adám wouldn't that end up with the last element in the vector always being ⍵?
@Aearnus Oops, yes, my bad. You're only subtracting two, and appending 0, so (⍵-96 64),0 and if you want to remove the last paren, "swap" the arguments of , to 0,⍨⍵-96 64
@Adám makes sense so far, thank you. Is there any better way to see if ⍵ is within that range? before the compression
@Aearnus There are some options, but let's just continue with this for now.
sounds good!
@Aearnus We can do the same kind of combination and swapping on the left: 1,⍨(⍵≥97 65)∧⍵≤122 90
So we have {↑(1,⍨(⍵≥97 65)∧⍵≤122 90)/0,⍨⍵-96 64}
Now that it has been cleaned up a bit, we can see that 1 is always paired with 0 so we always append a 0 on the far right, no matter what is.
This means that we can "break out" the 0 from the compression: {↑0,⍨((⍵≥97 65)∧⍵≤122 90)/⍵-96 64}
10:34
sorry for the clarification, but what's ⍨ exactly?
@Aearnus is an operator which swaps the arguments of the function to its left, so 10-⍨3 is ¯7.
ah, thank you
@Aearnus Can I ask which APL you use and if Dyalog, what the value of ⎕ML is?
@Adám ⎕ML doesn't seem to exist, and I'm using GNU APL 1.7
@Aearnus Ah, OK, then may not exist either. I'm not so familiar with GNU APL.
10:37
@Adám it does indeed exist
I've been putting this all into the interpreter as we go
@Aearnus Oh, good. I don't know where to find documentation for GNU APL.
@Adám I don't either, haha. I checked out an APL2 book from the library earlier and I haven't run into a bit of code that hasn't worked in my interpreter though
@Aearnus I think you can safely remove the 0,⍨ part btw, because if the argument doesn't fall in any of the ranges, then the compression ends up giving an empty numeric vector, and the first ( in GNU APL) element of that coerces out a prototypical 0.
@Aearnus Right, I think GNU APL is pretty much a superset of APL2 maybe except for certain advanced system features.
@Adám getting rid of the 0 does seem to work
so now I have normalize←{↑((⍵≥97 65)∧⍵≤122 90)/(⍵-96 64)}
@Aearnus Remember that APL is right-associative, so you can always remove parentheses from a trailing part of an expression.
10:42
ah yeah
@Adám if there's anything like J's fork (code.jsoftware.com/wiki/Vocabulary/fork) that would make those comparisons much easier, no?
not sure if that exists or not
@Aearnus I don't think GNU APL has those. Dyalog, NARS, ngn, and dzaima have that.
@Adám I could give it a try anyway. What's the syntax for it?
@Aearnus Exactly like in J. (f g h)⍵ is (f ⍵)g(h ⍵)
@Aearnus Here is another thing you can do: The two subtractions are really unnecessary, as you will only ever subtract at most one, so you can write: {↑⍵-((⍵≥97 65)∧⍵≤122 90)/96 64}
@Adám that does look nicer
@Aearnus Now here is a think I'm not sure about in GNU APL: whether can swap the arguments of / or not. If it can, then {↑⍵-96 64/⍨(⍵≥97 65)∧⍵≤122 90} should work.
10:51
@Adám it looks like it works, but it's doing strange things to my interpreter. I'll stick to the other version
@Aearnus What I often do is define a helper function: where←{⍵/⍺}
@Adám that would have the same precedence as /, right?
wait. everything has the same precedence. That's a bad question
@Aearnus I doubt GNU APL has dyadic , but if it does, then that is a better way to find the interval where a number occurs.
@Adám It's on my GNU APL emacs keybinding, so it seems like it has it. It doesn't give me any info about how to use it, though. What do I do with it?
@Aearnus Just a min, I'll show you.
⍞←65 91 97 123⍸⎕UCS 'Hi! ~'
10:58
@Adám 1 3 0 0 4
@Aearnus It tells you the index of the interval were an item fits.
@Adám Hmm, that sounds super useful. I feel like it'd be just as unwieldy though to check if it's in interval 1 or 3 (which is what I'm looking for in this specific example)
@Aearnus Well, you could e.g. phrase it as:
⍞←{⍵-⍵ 64 ⍵ 96 ⍵[1+65 91 97 123⍸⍵]}¨⎕UCS'Hi! ~'
@Adám 8 9 0 0 0
@Adám ahh, that's clever! I like that a lot
11:03
@Aearnus Does that work in GNU?
@Adám shoot, no, it doesn't
@Aearnus Come to Dyalog then! :-)
@Adám that's quite the convincing argument!
@Aearnus Dyalog has added quite a lot of fancy functionality to APL lately. Are you interested in other approaches to your specific problem?
@Adám I would be, but there's more to it.
Now I have a vector defined as `{⍵<normalize¨ ⎕UCS ⍺}`, and I want to use that to take the characters of ⍺ and keep them the same if 1, or replace with a space if 0
{(⍵<normalize¨ ⎕UCS ⍺)/⍺} would work if it didn't just remove the characters -- but it's very close to what I want
11:09
@Aearnus Here:
⍞←{27|⍵⍳⍨'ABCDEFGHIJKLMNOPQRSTUVWXYZ',0,'abcdefghijklmnopqrstuvwxyz'}'Hi! ~'
@Adám 8 9 0 0 0
Additionally: does dyalog offer student licenses? :)
@Aearnus Yes, and personal licenses. They are all free.
sounds fantastic!
Notice that a) we can operate straight on the characters, rather than their code points, and b) we don't need to loop with ¨ any more.
Now, listing the alphabets may be a bit verbose, but some APLs (e.g. Dyalog) have ⎕A which is the uppercase alphabet, and a special service (819⌶) to lowercase, so it can be written as ⎕A,0,819⌶⎕A
11:12
@Adám what's the purpose of the 0 in the middle?
actually -- I don't think I understand much of what's happening there
oh, the 0 will be the default value of the iota, won't it?
@Aearnus Items that do not occur get the index of 1+ the last index, so if it was just a single alphabet (all uppercase) we could get away with 27|'ABC...Z'⍳⍵ but since we have lowercase as well, 'a' would also end up 0, so we push it one step right by inserting an element that won't hurt. Could have been any non-letter too.
ah, that makes sense
@Aearnus Right, you have code to compress away the unwanted elements, but now you want to expand with an inserted space in those exact same location. Luckily, APL has an expand function \
@Adám VALUE ERROR
@Adám ah! It didn't occur to me that compress and expand were sort of like duals to each other
hold on -- don't give it to me
11:19
Oops, of course the bot doesn't know what normalize is.
let me try to figure it out first
@Adám {(⍵<normalize¨ ⎕UCS ⍺)\(⍵<normalize¨ ⎕UCS ⍺)/⍺} seems to work, but it also seems like it's completely unnecessarily long
@Aearnus That is exactly right. I'm not sure if GNU APL now allows multi-statement lambdas or not. Dyalog does: {b←⍵<normalize¨ ⎕UCS ⍺ ⋄ b\b/⍺}
Even if it doesn't, you can surely combine statements with as follows: {b\b/⍺ ⊣ b←⍵<normalize¨ ⎕UCS ⍺} where is read as the word where :-)
@Adám that indeed does work! also: I'm currently applying for a personal dyalog license; it seems to have made its case haha
thank you for all of the help
@Aearnus You should get the license still today. Made its case, just wait and see. Dyalog has introduced the @ operator which appropriately amends its argument at locations indicated by its right operand. E.g. you can add 10 to the third element with 10+@3:
ahh! That seems overwhelmingly convenient
11:30
⍞←10+@3 ⊢ 3 1 4 1 5
@Adám 3 1 14 1 5
@Aearnus If the right operand is a function, it must return a mask that indicates where the changes are to be made, and the left operand can also be an array with substitution values:
⍞←'-'@{⍵∊'aeiou'}'Hello World!'
@Adám H-ll- W-rld!
@Adám that would have made this so much easier
@Aearnus Watch:
⋄ ⎕ML←3 ⋄ normalize←{↑⍵-((⍵≥97 65)∧⍵≤122 90)/96 64} ⋄ ⎕←' '@{8>normalize¨⎕UCS ⍵} 'Hi! ~ There.'
11:33
@Adám
Hi    Th r
@Aearnus ⎕ML←3 is Migration Level, and 3 means be as similar to APL2 as you can.
There are not too many differences. The most frequently encountered one is that the meanings of monadic and monadic are swapped. Also, monadic is a bit more informative in Dyalog's normal behaviour (⎕ML←1) and partition (dyadic ) has a different definition, but APL2's partition is always available as .
@Aearnus Also, Dyalog has really neatly integrated regular expressions, so you could also just have done:
⍞←'[\000-G]|[^A-Z]'⎕R' '⍠1⊢'Hi! ~ There.'
@Adám Hi    Th r
@Aearnus Of course, we could also just have used @ and uppercased lookup into the desired alphabet:
⍞←' '@{~(1(819⌶)⍵)∊6↓⎕A}'Hi! ~ There.'
@Adám Hi    Th r
1(819⌶)⍵ is uppercase.
11:46
@Adám I finished the entire expression I wanted to get at:

`{"HELLO WORLD" {b\b/⍺⊣b←⍵<{↑⍵-((⍵≥97 65)∧⍵≤122 90)/96 64}¨ ⎕UCS ⍺} ⍵}¨⍉1 26⍴⍳26`

it's messy and it uses some weird nested lambdas, but I wanted to see how short it could be.
@Aearnus (btw, you can't use markdown in multi-line messages, but if you write multiple messages right after each other, the system will merge them visually.)
and wow -- that's a really tiny version of pretty much exactly what it took me a few hours to do
@Adám (ah, I'll keep that in mind)
@Aearnus Also, feel free to use the bot. Any message beginning with ⎕← or ⍞← or ⋄ is evaluated as APL.
⍞←'Hi @Aearnus'
@Adám Hi @Aearnus
@Aearnus ⍉1 26⍴⍳26 is just ⍪⍳26
11:53
oh, that makes a ton more sense than what I did
@Aearnus My shortest so far:
⎕←⍕ {' '@(~(⍵↓⎕A)∊⍨819⌶⍨∘1)'Hello World!'}¨⍪⍳26
@Adám
 Hello World
 Hello World
 Hello World
 Hello Worl
 H llo Worl
 H llo Worl
 H llo Worl
   llo Worl
   llo Worl
   llo Worl
   llo Worl
     o Wor
     o Wor
     o Wor
       W r
       W r
       W r
       W
       W
       W
       W
       W
The is to avoid drawing a lot of lines indicating nestedness which would make the output very verbose.
@Aearnus Note that your "real" argument, which is the string, is hard-coded into your lambda. This is hardly desirable, but you can of course code around that with an additional lambda layer: {⍵∘{' '@(~(⍵↓⎕A)∊⍨819⌶⍨∘1)⍺}¨⍪⍳26}
@Adám I ended up doing it like this:
W←⍞◊W◊{W{b\b/⍺⊣b←⍵<{↑⍵-((⍵≥97 65)∧⍵≤122 90)/96 64}¨⎕UCS ⍺}⍵}¨⍪⍳26
(it's a code golf challenge between a few friends and I, and one of the requirements was the original string still had to be printed on the first line, hence the lone W)
@Aearnus What should the second line contain in the case of Alpha-Bet? Should it be Alpha Bet or lph Bet?
12:06
@Adám ` lph Bet`
@Aearnus So there is no line where only non-letters are blanked out, but As are preserved?
@Adám other than the top line (which remains unchanged), yes
@Aearnus Also, you may notice that all but the first line are indented one space. This is due to the result being nested. If you remove the and instead put on the left of the left-most { then it will line up better. In fact, then you can even replace the diamond there with a so the full result is truly returned as a single array.
@Adám I did notice that, I was about to ask
thought I could employ some google-fu, but it didn't come back with anything
@Aearnus If GNU APL supports as an operator, you can write {⍵⍪⊃⍵∘{⍺{b\b/⍺⊣b←⍵<{↑⍵-((⍵≥97 65)∧⍵≤122 90)/96 64}¨⎕UCS ⍺}⍵}¨⍳26} to have a true lambda at the same character count. GNU may even allow you to remove the space in ⎕UCS ⍺.
12:15
@Adám what does ∘ do in that context? also, it did indeed let me remove the space after UCS.
@Aearnus used like that (of course only in APLs that support it) curries an argument to a function. So 1∘+ is the increment function and ÷∘2 is the halve function.
@Aearnus Here, I was using it to let ¨ apply the lambda with a bound argument as a monadic function. Without it would try to pair the letters of the string with the 26 numbers.
@Adám currying! That's a comforting tool to have (coming from a Haskell background)
Makes a lot of sense. I'm going to put this project on the shelf for the night though -- early classes tomorrow. Thank you so much for all of this help! I appreciate it
@Aearnus Yes, but it does more than that, it is generally called composition as it composes an argument with a function, but it can also compose two functions exactly like the identical symbol is used in traditional mathematical notation, so you can define a new function f←g∘h which when applied to x gives you f(g(x)).
@Aearnus Not a problem at all. You're always welcome, and there are more people here than me who are happy to help. Once you have Dyalog APL installed, you may want to look at our lessons for features that don't exist in GNU APL.
Will do!
 
3 hours later…
15:05
@Adám wrote a quick solution to your latest challenge, gonna golf it later: {^/(10≤≢⍵)(3≥+/⎕D∊⍵)(⍵≢⌽⍵)}
15:47
Working for fun on a Pentaminoes 5x5x5 Cube Puzzle check it out at https://www.youtube.com/watch?v=PjmFjIDYdiw I enjoyed so much the process of making the program using Dyalog APL. @dyalogapl
Our CXO, @mkromberg, together with Ray Polivka, is proud to be giving a lecture for The Winifred Asprey Lecture Series in Computer Science at @Vassar College. Details of the lecture can be found here https://www.cs.vassar.edu/_media/events/individual_events/apl_2019-2-13_ray_polivka_morten_kromberg_11x17_flyer.pdf

« first day (749 days earlier)      last day (2202 days later) »