« first day (1587 days earlier)      last day (1070 days later) » 

9:32 AM
CMC: Shortest function to exhibit this behaviour:
      1 f 2 3
SYNTAX ERROR: The function requires a left argument
      1 f 2 3
        ∧
 
      f←∧⊢ ⋄ 1 f 2 3
SYNTAX ERROR: The function requires a left argument
      f←∧⊢ ⋄ 1 f 2 3
               ∧
I win?
 
Yes, indeed. That's exactly what I had.
CMC: Shortest function to exhibit this behaviour:
      1 f 2 3
SYNTAX ERROR
      1 f 2 3
        ∧
 
9:48 AM
      f←¨ ⋄ 1 f 2 3
SYNTAX ERROR
      f←¨ ⋄ 1 f 2 3
              ∧
Oh, it should be a function?
 
Yes, it must be a function. I.e. 3=⎕NC'f'
 
      f←1¨ ⋄ 1 f 2 3
SYNTAX ERROR
      f←1¨ ⋄ 1 f 2 3
               ∧
Apparently syntax errors in a dfn do not show the caret
 
Nice. That's shorter than mine.
@Bubbler Wat?
 
      f←{⊢} ⋄ 1 f 2 3
SYNTAX ERROR
      f←{⊢} ⋄ 1 f 2 3
(I'm using tryapl executor btw)
 
9:54 AM
Oh, ok. Too lazy to fire up the interpreter
 
@Bubbler I see. My fault then. In TryAPL, I manipulate the error message to hide the fact that it isn't a real session, but rather is running inside inside some other code in a thread… As I adjust the position, I seem to end up deleting it :-(
@Bubbler I've logged an issue on GitHub.
@JosephAdams Hi there. Interested in APL?
 
10:57 AM
@Adám Hey Adam! Yes, recently my interest in learning APL (or more generally array-oriented programming languages) has flared up again, after being dormant for a couple of years. I heard the APL Orchard is a great place to hang out and find like-minded people -- though up until now I've been more of an observer...
 
@JosephAdams You're welcome to lurk, but do let me know if I can be of help with anything, be it specific questions, 1-on-1 training, links to resources, etc.
 
@JosephAdams welcome
 
11:20 AM
Thank to you both! -- I do in fact have a question that's been bugging me for a couple days (about as long as I've been trying out APL) for which my Google-foo seems insufficent: is there a simple way in (Dyalog) APL to display the "parser-boxing", for lack of a better name, of a dfn? like I would get for a tacit function? i.e. a similar thing to what I get when entering ⊂∘⍋⌷⊢ but for {(⊂⍋⍵)⌷⍵}
I find myself still struggling a lot with the "boxing" order when trying to be tacit -- sometimes I'll be able to write a dfn that does what I want, but converting that to its tacit variant is more difficult without the parse tree
 
don't think there's anything like that, but control flow in dfns is generally easier to trace because of the right to left execution
 
11:53 AM
Ah okay, maybe that was another source of confusion for me -- I didn't realize that inside dfns the order-of-operations is always right to left (rather than e.g. forks being parsed), thanks for the clarification
 
no, dfns still parse forks & whatever. Parsing in dfns is just like parsing in the REPL though
(with the obvious difference that there's also and defined as array variables (and ⍺⍺ and ⍵⍵ for custom operators))
 
Right - trains are just a type of function composition when there are 2 or more functions in isolation. Previously 3{⍺(+,-)⍵}4 would have been a syntax error
 
I see, I see - so, at the moment, the only/best way to convert from dfn to train is to "bubble" ⍺ and ⍵ left and right until they only appear on the far sides of the dfn, like in RikedyP's example
 
Hmm I should probably set up a matrix client and go to the right place for this but... how do you do inner / outer product in bqn?
 
@goof outer - ; inner - do it yourself with
this lists f.g as f˝∘g⎉1‿∞
 
12:14 PM
Thanks. I like but f˝∘g⎉1‿∞ looks quite goofy :)
 
@goof well, full f.g on both args with rank>1 is pretty much only seen in proper math algebra stuff, which BQN doesn't place that much focus on (and for rank=1 you of course have simpler things)
 
I supposed that if you need it a lot, it is as simple as defining _dot_←{𝔽˝∘𝔾⎉1‿∞} once.
 
Huh. Didn't know you could do that.
 
I might change the interface to use •CustomBQN that replaces all the primitives, with •primitives to keep the old ones.
 
 
1 hour later…
1:46 PM
Question: I've managed to reduce the dfn {(2</⍵) (2=/⍵) (2>/⍵)} to the train 2∘(</,⍥⊆=/,⍥⊆>/) -- but I feel that the repetition of the over nest might be bad style. Is there a way to further improve?
 
looks good to me
 
RGS
@JosephAdams The thing is that your dfn uses stranding to create three things, and inside trains you cannot do stranding like that, and that's why you use ,⍥⊆ so much... It's not lack of skill from your side
 
yea, there's not really anything better
 
RGS
This goes to show that trains aren't always better.
 
ah okay, so it (surprisingly) wasn't lack of skill -- thanks!
@RGS hmm, I've got to say I also find the dfn variant more clear -- though (possibly coming from a Haskell context) I've been indoctrinated with the conception that pointfree/tacit is always to be preferred
 
RGS
1:59 PM
@JosephAdams Yeah, I'd argue against that. I find elegance and beauty in tacit definitions, but I don't think tacit ≡ superior.
 
I'd say in that example the dfn is better, but in something like {(+⌿⍵)÷≢⍵} (+⌿÷≢) is much nicer
 
RGS
↑ the lack of punctuation makes it hard to parse the msg, rak
 
@rak1507 I feel that the latter is to be preferred because "there's no added fuss" in order to make the expression work as a train
 
RGS
In this chatroom you will see huge trains, but that's because people in here live and breathe code golf, where the only thing that matters is byte count.
 
@JosephAdams yeah
@RGS lol yep readability? what's that :P
 
RGS
2:01 PM
I can even go so far as to confessing I feel tradfns sometimes are the superior alternative
 
@RGS blasphemy :P
 
RGS
Even though some people here might gag upon reading that message :P
 
I just don't like having to do ;a;b;c;d;e...
 
RGS
@rak1507 I also hate that part :( but sometimes it is worth it.
 
not convinced :P
 
RGS
2:05 PM
I'll try to convince you some other time, now I gotta run.
 
@RGS I was just going to ask for an example.
 
RGS
I think this looks good as a tradfn github.com/RojerGS/ANNAPL/blob/main/Layer.aplf
Also, up to this point, any script-like functionality you needed made much more sense as a tradfn than as a dfn.
E.g. how would someone rewrite github.com/RojerGS/ANNAPL/blob/main/examples/mnist.aplf properly only with dfns? And at what cost?
 
Layer ← {
    ⍝ Create a layer of a neural network.
    ⍝ `(in out) ← shape` is a pair of integers
    ⍝ that specify the sizes of the input and output vectors of the layer.
    ⍝ `actFn` is a reference to a namespace that defines functions F and dF.

    layer ← ⎕NS⍬
    layer.shape ← shape
    Std ← ÷0.5*⍨×/
    layer.weights ← ((0,Std) MakeNormalRandomArray   ⌽)   shape
    layer.bias    ← ((0,Std) MakeNormalRandomArray ,∘1) 1↓shape
    layer.ActFn_ ← ⎕NS actFn
    layer⊣layer.⎕DF '(',')',⍨(⊃¯1↑'.'(≠⊆⊢)⍕actFn),' ',(⊃⎕SI),' ',⍕shape
I think this is the same? not sure...
 
RGS
@rak1507 Yeah looks the same
But that ⊣ is just cheeky :P
 
control structures are harder
lol
 
RGS
2:11 PM
yeah
 
      +/-\∘.-⍨⍳10
5 10 15 20 25 30 35 40 45 50
fun discoveries when playing with random stuff
 
2:41 PM
@RGS Your first example is easily converted to a dfn, as rak1507 showed. I don't see any reason your second example would not be made shorter and clearer by using dfns, unless one has a strong aversion to having multiple named dfns over one large trad fn.
In his last ArrayCast, Connor Hoekstra relayed a comment by a c++ guru that one shouldn't use "naked for loops". This is true most all control structures. If you name your control structure, put it in a function, you will find the keywords can generally be dispensed with, so you can use a dfn.
You can also then omit the comment line that is now duplicating the name of the function.
 
@JosephAdams Sorry I kind of came and left - but if you want my view, I did a webinar on trains in Dyalog a while back: dyalog.tv/Webinar/?v=Enlh5qwwDuY
 
@RikedyP great, thanks for sharing! I'll have a look at that
 
3:00 PM
@RGS In addition, rewriting MNIST using multiple dfns would help with writing code at the same level of abstraction. Right now MNIST is all over the abstraction map, combining code-golf with control structures and input and output.
 
RGS
@PaulMansour I didn't say Layer was hard to rewrite as a dfn! I don't view this as matter of being able to write it as a dfn or not, I find this is a matter of semantics... The order of the statements in Layer is almost irrelevant, because I'm not manipulating data or anything like that, I'm just packaging some things together, whereas I like my dfns to transform data and etc.
Also, MNIST is to be looked at as a "script", not as a regular function. I also didn't say it would be Impossible to have MNIST rewritten as a dfn calling other dfns, I just wonder what the price would be. For example, to loop over the training and testing data,how would you write it cleanly as a (series of) dfn(s)? This is a legit question, because I did have all of that code as dfns and dops originally, but I didn't like the style.
(I also wonder where in MNIST you are seeing code-golf :O)
Maybe I should write this as a code-review question in codereview.SE
 
I have to say, although I don't have a strong view yet, that I like the idea of tradfns being used for high level program control and system interactions, and dfns are more for the core data transformations that constitute your algorithms. It is also nice when dfns say "I have no side effects" and tradfns say "I might have side effects" imho.
 
3:21 PM
@RGS Regarding code-golf, what is the purpose of the embedded assignment on line 18 and the commute operator on line 17? Certainly not clarity, but only to save a line and save a character. Mo?
No?
 
RGS
@PaulMansour I prefer ft ← 0 ⎕NTIE⍨dir,'mnist_train.csv' over `ft ← (dir,'mnist_train.csv)⎕NTIE 0', I wasn't trying to save one or two bytes.
As for the inline assignment (of which there are 2 that are exactly the same), each one of them is saving me at least two lines, and the inline assignment is clear, short, readable, and in the "middle" (beginning, really) of a short statement.
Is it that unreadable..?
Again, fairly honest question. I don't know many people that write APL so it's not like I can call my friends and ask them if I'm writing idiomatic APL or trash.
 
@RikedyP I think more important than trad fn vs dfn is that code is written at the same level of abstraction. This requires many well-named sub functions vs one large function with lots of control structures and no named entities.
@RGS It's not unreadable, but embedded assignment always makes code harder to read. You cannot scan down the left side of a function and see where a variable is assigned.
Its easy to miss an assignment.
 
3:38 PM
@user3821550 Hi there. If you want to participate in this chat, please email access@apl.chat
 
I think the embedded assignment is very standard, it's basically
while (x := whatever()):
...
in python or
while (thing = whatever()) {}
in c, both pretty standard and idiomatic
 
@rak1507 Loops are idiomatic in c too.
Clearly, though, the point is to save a line of code, not make the code clearer, no?
 
so you're suggesting
data ← ReadChunk ft
:While 0<≢data
...
data ← ReadChunk ft
:EndWhile

over

:While 0<≢data ← ReadChunk ft
...
:EndWhile
?
 
RGS
@PaulMansour This is a very valid point, and in general I avoid inline assignments when writing APL.
 
@PaulMansour I would say it does make the code clearer, 'while the length of data gets ReadChunk ft is greater than 0'
 
RGS
3:45 PM
but for this particular case, I think this inline assignment is preferable to any other alternative I could come up with. data is a variable that has a "short scope" and its inline assignment is right next to the place where it is used, so I don't think it looks that bad.
 
I think it could be done with ⍣ not :while
 
RGS
@rak1507 "it can", but will it look good..? :/
 
@rak1507 Yes, as a start. The embedded assignment is particularly bad dangling off a control structure.
 
whether or not that's any 'better' is just up to opinion
@PaulMansour huh, well, I definitely disagree, but each to their own
 
@RGS Precisely why the whole block should be properly named and put in a function (preferabley a dfn: ;) )
 
3:47 PM
@PaulMansour It's solving the problem of you not being able to execute code before the condition. Otherwise you have to either extract the condition and use while(true), or duplicate code (which is bad)
 
RGS
@PaulMansour on the other hand, I do agree that inline assignments are just a recipe for disaster... However, you are yet to convince me that you have a better alternative that does not use inline assignments :)
@PaulMansour So I'll cut that piece of code, name it TrainNet, and then paste the exact same piece of code inside TrainNet? I just moved the problem elsewhere :P
So I'm missing something that you haven't been able to put across yet.
 
_←{~×≢data←ReadChunk ft:⍬⋄to←(⍳10)∘.=⍨⊃(t i)←SplitData data⋄∇to(net ##._Train)⍥⍪⍤1⊢i}
 
@dzaima I don't understand that. Is that this particular case (RGS's function) or some other place where it is required? Can you give me an example?
 
@PaulMansour how would you write RGS's function?
these are the options I see for RGS's function (i too have no clue how naming the inner loop body as a function helps anything)
 
@dzaima you didn't include my one :(
oh, it's missing a ⍬ at the end to actually call it, oops
 
3:59 PM
@rak1507 well, keeping a tradfn with :While
 
yea
 
@RGS You havn't just moved the problem elsewhere. By simply naming putting the loop in a function as is, you get localization. So now, the reader is not confused that you are using the same variables all over the place.
 
@PaulMansour "using the same variables all over the place" what?
 
data, targets, inputs, are reassigned multiple times, no? In different contexts? No?
 
that is what a loop does
 
4:04 PM
Wen reading code, is it not nice to know the scope of a variable?
No, its being done in different loops
same variables, different loops.
 
same variable name, sure, but different context, seems pretty clear to me
 
@PaulMansour If a variable is defined in a loop, I'll just assume it's scope ends at the loop end. (and that is what's happening in RGS's function, no?)
 
the only thing 'unreadable' in that code is (⊢⌹=⍨)outs
@RGS wtf is that! :P
 
@dzaima (oh right, Dyalog is strange and annoying and outdated and variables leak outside of the loop because of course they would :|)
 
@dzaima true in python too
 
4:07 PM
One reason RGS gave for the embedded assignment is that the data var is local to the loop block. In APL we gave a very nice way to deal with that. It's called a function.
 
@PaulMansour you still haven't said how you would rewrite it
 
@PaulMansour You need to define the data variable before the function is evaluated though. That's the whole reason for the inline assignment
the way rak wrote it ({data←ReadChunk ft ⋄ 0=≢data:exit or something ⋄ do iteration ⋄ ∇⍵}) or its tradfn alternative (the 3rd option of the ones I gave) are the only ways I see to rewrite the function without inline assignment or code duplication (or changing the algorithm)
 
RGS
I use the same name twice, because in both loops I am doing similar things, but I don't use the variables outside of the loops.
@rak1507 this is what I thought people would complain about; it's just a bad habit I have to break xD
 
@RGS why do that over +/÷≢
 
@RGS You know that, but the reader does not.
 
4:21 PM
other than to flex your obscure average calculations knowledge :P
@PaulMansour yes they do, if they read the code
 
@dzaima I thought RGS said the reason was to save a line of code? I'm running out, but I will attempt a rewrite later today. Probably you all are correct and I am missing something.
 
RGS
4:33 PM
@rak1507 just because I'm silly
 
lol
 
RGS
@dzaima (btw your third alternative has an extra data ← assignment at the end of the loop, I think you can remove that because you already have the top assignment.)
 
@RGS oh, whoops, yeah
 
RGS
@PaulMansour I look forward to your proposal! I'm always keen on learning smth new and I hope your rewrite sheds some light on your suggested preferred style.
 
5:26 PM
@SohangChopra Hi there. Interested in APL?
 
6:20 PM
@dzaima Sorry, I was doing two things at once before and not looking closely at RGS's function. Yes, with way RGS wrote it the inline assignment is needed. I would rewrite the code like rak1507 using recursion.
 
@PaulMansour well, I personally find recustion a ton more unreadable than inline assignment
 
6:36 PM
@dzaima Noted. I see a lot of embedded assignment dangled off the end of a control structures (like :If and the rest) where its only purpose is to save a line. Usually obscuring large and important functionality in the :If clause. I think its better to just do the big important thing on its own line. I mean, if one is using control structures, saving a line can't be a high priority.
 
@PaulMansour for if, it's a bit more strange, but it does give the idea of the variable being local to the following block (whether or not the language actually gives you that is unrelated). For while, as discussed, it's kind of necessary to get the wanted behavior.
(and the condition of a control structure is like the most important place in any function, so someone not reading it while reading other boring regular lines would be strange)
 
6:52 PM
@dzaima It's interesting about :While vs :If . I wonder if any other control structures require embedded assignment for certain tasks... I haven't thought about it..
 
well, traditional language for loops pretty much always have embedded assignment
 
True that!
 
(but other than that, since most traditional languages don't allow declaring a variable in the condition, just reassign an already defined one, it doesn't give you much)
@dzaima (still, of course, outside of while loops)
 
 
1 hour later…
8:23 PM
Is it somehow possible to select multiple elements with ⌷?
 
Yes, enclose the list of indices:
      (⊂5 3 2)⌷'Hello'
ole
Alternatively, you can use rank:
      5 3 2⌷⍤0 99⊢'Hello'
ole
 
hello everyone, there seems to be a lot of APL like languages. which are the simplest to implement? i'd be using megaparsec in Haskell for parsing.
ideally a context free grammar would be nice
 
If you want context free grammar, then apl.wiki/K and apl.wiki/BQN are your only options.
However, all it takes for APL to become context free is a strict naming convention (that's what BQN uses).
 
what do you mean by a strict naming convention?
 
The problem is in expressions like a b c
You don't know what the names stand for.
It could be that a and c are arrays, which are arguments to b.
It could be that a and b are functions: a(b(c))
It could be that a is a function and b a monadic operator.
It could be that all three are functions, and the expression is a tacit function.
It could be that a and c are functions, and b is a dyadic operator, deriving a function.
And there are more options.
 
8:33 PM
ahh thank you
would K be the simplest APL to implement?
i'll be using strict naming convention
some kind of restriction on the variable names for dyadic functions, monadic functions etc
 
If you consider it an APL, yes.
 
so like a variant of an APL
 
I think K is simplest. However, it doesn't need a naming convention, because it doesn't allow infix user-defined functions.
Another issue is stranding, as in a b c where a is a function while b and c are arrays, forming a larger array which a is applied to.
 
I can't seem to figure out how selecting multiple elements from a multi-dimensional array works though. Say a is a←⊃∘.,/3⍴⊂1 2 3. (shape is 3 3 3). Then a[(0 0 0)(2 2 2)] works, but I've yet to do the same with .
 
k also only has a limited selection of monadic operators, and no user-defined ones. All variables are interpreted as nouns/values
 
8:36 PM
K and J solve this by prohibiting stranding. BQN solves it by using a different symbol for stranding.
 
There is some difficulty in finding resources that explain how K works. BQN (which is my language) has a specification.
 
that's wonderful :))))
 
about k - people like throwing around the single-line grammar: E:E;e|e e:nve|te| t:n|v v:tA|V n:t[E]|(E)|{E}|N; Have fun trying to figure out what's what though.
 
@goof I don't see how a[(0 0 0)(2 2 2)] works there. Can you link to TIO or TryAPL to show me?
 
@Adám uh it just does?
 
 
I must have mistyped something ¯\_(⍨)_/¯
Oh man, I had a stray on a
@goof (0 0 0)(2 2 2)⌷⍨∘⊃⍨⍤0 99⊢a
Ugh, there that stray was again!
 
9:14 PM
Hm. Tryapl froze again.. maybe it was justified this time because I had a large-ish array but shouldn't it at least timeout
 
It should.
It loads for me.
 
Yeah it loads for me too
 
It'd be nice to know exactly what you do to freeze it.
 
If I hit refresh, it'll load just fine again.. and be fine again for a while.. until I freeze it again
 
:-(
While we should fix that, have you considered a local interpreter?
 
9:23 PM
How long is the timeout supposed to be?
"Expressions may run for up to 10 seconds" which I guess is the server side limit? But the user interface probably has another timeout value
 
Ah, that's a good point. I'm not sure the frontend handles that cleanly.
 

« first day (1587 days earlier)      last day (1070 days later) »