« first day (1437 days earlier)      last day (1218 days later) » 

12:04 AM
⎕UCS 1-⎕IO-⎕AV⍳'G⍙ÔÔðoÒÇãoðÇ⍙Ùp'
 
12:31 AM
@rak1507 Happy new year to you too! :)
 
ngn
@rak1507 ⎕io-independent - nice touch :) hny!
 
Couldn't leave you out :)
 
ngn
@rak1507 i'm not sure i'm in the minority in this respect
 
Oh do most people use ⎕IO←0?
Maybe I'm the minority!
 
ngn
@rak1507 i can't speak for dyalog users, but among array language users - yes. among any programmers - overwhelmingly yes.
 
12:44 AM
I think ⎕IO←0 would be better, but generally in APL I use ⎕IO←1 because of pure laziness
 
ngn
@rak1507 did you know you can change the default ⎕io with export DEFAULT_IO=0? :)
 
:O
No I didn't
 
ngn
(the default default is still 1)
 
What do you mean by default default?
 
ngn
the default value of $DEFAULT_IO
 
12:45 AM
Ah
is there a DEFAULT_DEFAULT_IO? lol
 
@rak1507 I'm assuming you used an expression to "encode" the string. I'm curious what it was, if you wouldn't mind sharing :)
 
⎕AV[⎕UCS'Happy new year!']
 
It's so freaking obvious once you point it out!
 
lol
 
ngn
@rak1507 hehe, afaik no :)
 
12:52 AM
Alright, I'm confused... How can that expression actually be ⎕IO independent? ⋄ 1-1-⎕AV⍳'G⍙ÔÔðoÒÇãoðÇ⍙Ùp'
 
1-1-x in APL is 1-1+x in normal maths
 
that yields a different vector than1-0-⎕AV⍳'G⍙ÔÔðoÒÇãoðÇ⍙Ùp'
 
@ab5tract did you execute that with ⎕IO←0?
 
⍳ is ⎕IO dependent
 
@dzaima facepalm.. yes, I had ⎕IO←0 when I was running it against hardcoded replacement values for ⎕IO in that expression
 
ngn
12:56 AM
use 0. always 0. ⎕io delenda est.
 
the magic is in the parity of ⎕IO and
 
Just write ⎕IO independent code all the time and never have to worry about it ;)
 
ngn
@rak1507 that's a lot more effort than ⎕io←0 & ignore the fools
 
3⊃/4⊃ bad, ⊃3⌽ best
 
<moon-child> ⎕IO←2 ?
 
12:58 AM
lol
⎕IO←.5
 
ngn
Dec 21 '20 at 19:04, by ngn
what i call the "solomonian solution"
 
Yeah
What if people did a poll and then ⎕IO was dependent on the results
20% of people vote for ⎕IO←1, clearly that means ⎕IO should be 0.2
 
Honestly I don't mind ⎕IO ← 1 nearly as much as I had expected to... it helps that for loops aren't a thing :)
 
ngn
@rak1507 democracy is tyranny of the majority
 
Alright tocqueville calm down
 
1:03 AM
@rak1507 in some rabbit hole recently I was reading an informal survey of index origin preferences in the J community
 
What were the conclusions?
 
ngn
j-sters have no choice anyway :)
 
@rak1507 exactly as ngn mentioned: no introduction of configurable index origin. the majority ruled ;)
 
ngn
@ab5tract that's actually true, it matters a lot less than one might think initially, but the default is still wrong and users shouldn't be bothered with this kind of choice.
 
I agree, I don't know why on earth they made it configurable in the first place...
 
1:08 AM
<klg> it should be that 0≠↑0⍴⎕IO and you have to always do ±⎕IO to convert between integers and indices ;)
 
@ngn 50+ years of backwards compat sure is a helluva lot to maintain
@rak1507 because it always has been. APL/360 had it, according to the book I'm currently reading from 1970
 
But why did they choose that?
Who was the first person who thought 'I know, this should be configurable!' and more importantly, why
 
ngn
@rak1507 iverson himself wanted 0. some "domain experts" wanted 1. it was a solomonian solution.
 
Experts in what, I assume not programming? Did any other languages at the time use ⎕IO←1?
 
There were only a handful. FORTRAN used 1. MATLAB uses 1.
Not that MATLAB was around at the time
 
1:13 AM
Huh, FORTRAN used 1, didn't know that
 
ngn
@rak1507 "domain expert" = a person who can't program but has enough control over money to change the way programmers behave
 
lol ouch
 
ngn
@ngn without the "control" part we would be calling them idiots
 
I think that's a bit harsh considering the times we are discussing. There were a great many lessons yet to be learned and very few examples to go by. I think mathematicians are in general more used to indexes starting at 1, or certainly were at the time
It's not exactly intuitive to go from saying "the first element of vector x" to using an index origin of 0
That said, I've just set ⎕IO to 0 in the Dyalog settings (Windows) :)
 
ngn
@ab5tract yes, but generally mathematicians can easily change habits. they understand starting from 1 is not essential, and in some parts of mathematics, like number theory, ⎕io←1 would actually be very unnatural. the residue classes modulo n traditionally go from 0 to n-1, not from 1 to n
 
1:20 AM
Fair, but again, this is over half a century ago. The book I have discusses operating systems as a newfangled concept
 
codegolf.stackexchange.com/questions/216902/… lol people calling ngn's solution code golf
 
ngn
@rak1507 yeah, "unreadable" etc.. :) actually, i'm in the middle of writing a better solution, using nfa->dfa conversion
 
idk what NFAs or DFAs are but cool
 
ngn
@rak1507 have you come across the chomsky hierarchy yet?
 
Nope
 
ngn
1:26 AM
@rak1507 if you're studying computer science (or something equivalent), you will
 
Probably won't be taught it for a few years then
 
ngn
NFA = non-deterministic finite automaton. DFA = deterministic
 
Ah
 
ngn
they are like graphs that have states (the vertices) and transitions (the labelled edges)
 
I think I've seen some examples before
 
ngn
1:28 AM
they can recognize languages (i.e. sets of strings) by consuming one char at a time and following the transitions
 
right, how does this apply to the question? I can see how you could potentially make a graph with all strings or something, but I'm not sure
 
@ngn "they" here meaning meaning chomsky hierarchies?
or DFA
 
ngn
@rak1507 there's a (relatively easy) way to build an nfa recognizing strings withing a particular edit distance from a given input string. if it can be converted to a dfa (there's a theorem+algorithm that says this is always possible), then recognition can be very efficient. so can be generation of recognized strings.
 
huh, well good luck with that, sounds interesting
 
ngn
@ab5tract dfa-s (or equivalently nfa-s)
 
1:33 AM
speaking of Levenhstein and languages with indexes starting at 1, Bertand Meyer just produced some videos on the topic in Eiffel: bertrandmeyer.com/2020/12/03/…
 
ngn
@ab5tract i believe it's easier to look it up in wikipedia than wait for me to describe it but.. the chomsky hierarchy consists of four proper nested classes of languages: regular (class 3), context-independent (2), context-sensitive (1), and general (class 0).
 
Even Chomsky uses index 0 ;D
 
ngn
each class has corresponding types of grammmars and some classes have corresponding types of automata that recognize them (i hope i got this right)
@ab5tract haha, nice observation :)
(i'm looking it up right now to make sure i'm not talking nonsense..)
ok, type 0 languages/grammars actually have a name: "recursively enumerable", but never mind..
we care most about the context-independent class, because that's what most programming languages are
 
@ngn I'll let it slide... but only just this once ;)
 
ngn
i forgot what i was going to say.. @rak1507 should i explain the levenshtein nfa construction?
(it's ok to stop me, sometimes i get too carried away writing about trivial details)
or maybe i should explain the difference between nfa and dfa?
 
1:47 AM
I'm interested in either approach. the explanation would cover the code you submitted, right?
 
ngn
@ab5tract the code i submitted is just bruteforce recursion
i'm still working on the clever nfa->dfa solution
 
ah , I misread what you meant about 'NFA -> DFA'
figured you already had the nfa and were working on a dfa version.
← is a compsci dropout
 
ngn
@ab5tract i would say i'm not 100% compsci either. it was right after the balkans' 1990s (terrible time), and i had to start work while studying at uni to make a living. somehow i managed to get through all exams.
in an nfa the transitions are from one state, consuming a particular symbol, to a set of states
in a dfa, the transitions are from one state, consuming a particular symbol, to exactly one other state
there's a famous algorithm for "determinization" of an nfa. the worst case could be O(2^n) where n is the number of nfa states, but in practice it's rarely that bad
 
@ngn I was at a free form liberal arts college where I could pursue many different topics -- and I have a lot (too many!) interests. On top of that I had already been earning paychecks as a programmer, so I figured "why would I need this?" ... youth and arrogance!
 
@ngn definitely! it's fascinating
 
ngn
2:00 AM
@rak1507 just one note about nfa-s: under some definitions, they could have "epsilon"-transitions - transitions that don't consume an input character. nfa-s with epsilons are equivalent to nfa-s without epsilons.
 
what's the definition of two things being equivalent?
 
ngn
@rak1507 two automata are equivalent iff they recognize the same languages
 
Makes sense
 
ngn
@rak1507 imagine a matrix of nfa states. the height of the matrix represents the number of edits we've made. the width of the matrix represents how much of the input string we've matched.
 
good morning
 
2:03 AM
happy new year Razetime. How's the future treating you?
 
ngn
@Razetime good year :)
 
Morning
 
the future looks fine idk
that will be decided when my exam results come up
any way, good year.
 
Did all your exams go ahead and stuff? Mine are cancelled bc of covid
 
we had them online
 
2:04 AM
Ah
@ngn So when you convert your program to use the other method, will the overhead of converting it be sufficiently low that overall the other method is faster?
 
ngn
what does it mean to insert a char? - we move down in the matrix (number of edits increases, number of matched chars stays the same)
what does it mean to delete a char? - we move down and right in the matrix without consuming an input char (so it's an epsilon transition)
what does it mean to replace a char? we move down and right while consuming
and what does it mean to match an input char without an edit? - we just move right
this way we can build an nfa, relatively easily
then use the O(2^n) algorithm to turn it into a dfa
and then we can do whatever we want!
 
O(2^n) sounds like a lot, what's the time complexity of your current algorithm?
 
ngn
like match strings from the language (language = set of strings within edit distance 2 from the given string)
or generate the whole language
 
The entire thing
 
ngn
@rak1507 the upper bound is O(2^n) but due to the structure of this particular kind of nfa, it's still fast
O(2^n) is just worst-case
 
2:11 AM
Cool, I assume doing it in APL would be pretty unrealistic? Sounds like it's quite scalar code
 
ngn
@rak1507 it's not impossible. as usual, apl (or any array language) would have some advantages and some disadvantages
 
It doesn't sound like something where array operations would be ideal, maybe generating all strings could be done with some sort of outer product but I'm not sure
 
ngn
@rak1507 the challenge is tagged "fastest code", and it's not just basic arith on long vectors, so i'm not even trying with array languages
 
But the bounty says they'll choose the 'most impressive' solution from the fastest submissions in each language, in which case maybe APL is more impressive than C? ;)
 
ngn
@rak1507 "most impressive" would probably imply a , but it was tagged
 
2:16 AM
'For each language I will look at the fastest solution. I will then choose the answer out of those that I find the most impressive.'
 
ngn
there is only one bounty (i don't really care about rep, of course, but it's a fun challenge for me)
 
Yeah, and it looks like it's not even going to be awarded based on code speed, but on the impressiveness, which is weird
 
ngn
@rak1507 in that case i'd be happy to lose, as long as my algorithm works better
bruteforce is not so easy to beat, by the way
 
I probably won't try, it all seems way over my head still
 
ngn
@rak1507 yeah, it's not too simple. better wait until you're introduced to automata theory by a professional teacher.
it's not too complicated either. i'm just not so good at explaining things.
 
2:28 AM
No, you explained it well, there's just a large difference between sorta getting it conceptually and being able to use and implement it in practice
 
ngn
i hope i can finish my c solution in the next few days. you'd probably be able to figure out the details from there.
btw, user Anush (and now his friend fomin) has been posting variations on the same challenge for years! :)
 
yeah, but who can really blame them
 
Oh yeah
Must be interested in that stuff I guess
 
ngn
@Razetime i don't. many of these are great challenges.
 
Somehow their names are not levenshtein neighbours
 
ngn
2:38 AM
:D
 
 
4 hours later…
7:06 AM
@ab5tract Basic uses 1. Of the current popular languages, the only one I know of that still uses 1 is Lua.
@ab5tract Well, I started at the beginning of COVID, first commit is 8'th of January. I've been working on it on and off during the year in parallel with some other projects.
@ngn Maths people tend to use 1, for some reason. Probably tradition. The reason they get away with is is because you rarely actually do arithmetic on indexes the way you do in programming.
Then you have the "regular people" who cannot understand the difference between ordinals and cardinals. Except in the anglosphere, people do seem to have no problems dealing with it when it comes to centuries (19'th century being 18-something)
I also note that R uses 1-based indexing.
 
 
1 hour later…
8:49 AM
<moon-child> julia also uses 1-based indexing
<moon-child> is quite popular for scitech (and possibly some fintech too?)
 
9:16 AM
Mathematica (Wolfram Language) also uses 1.
@ab5tract COBOL had 1 too. Several other languages, contemporary to APL, had 1 too, e.g. PL/1 and Smalltalk, Other examples of languages used today that have 1 are AWK and XPath/XQuery.
 
9:35 AM
@Adám With this and cvzi's suggestion, it now works with the latest ngn-apl version
 
cvzi?
 
cvzi's the person who helped fix the script on SO
 
Ah, cuzi.
 
you know them?
 
No.
 
9:38 AM
alright
so the userscript should update when I push to github right
 
Yes, but now you're using ngn/apl instead of TryAPL?
 
nono
this one's the aplChat script
the one which executes stuff outside the textbox
 
Ah, ok, sorry. Still early here.
 
the tryAPL script is still the same
 
For that, you may want to switch to the ngn/apl hosted on my GitHub account. ngn said he'd take down his (today?)
 
9:41 AM
oh lmao
just a moment
done
 
I have a parsing question. Consider the following toplevel definition: foo ← { ⍵+1 }
Then, the following second toplevel definition: b ← { foo ← {⍵+3} ⋄ foo ⍵ }
I'm implementing support for this syntax in Kap right now (for familiarity of users).
Now, I end up with a difficult-to-solve parsing issue here.
In the second line, the parser first sees foo and rightfully determines it's a function, so it attempts to parse everything to the right as the arguments to foo. The next thing is sees is ← so it bombs out with an error because there is nothing on the left side of the arrow,
How does the Dyalog parser handle this?
And for that matter, any other parser.
 
<moon-child> ← should have higher precedence than function application, so should get parsed first
<moon-child> stranding > ← > operator app > function app
 
I don't think that's right.
In the second line, the assignment to foo is local to b, and so the toplevel def is ignored/shadowed.
 
@Adám True, but since parsing is left-to-right (which is the case in Dyalog too, if I'm not mistaken) foo has been parsed as a function application before the arrow is seen.
 
No, Dyalog's parsing is token based, not syntactic role based.
In Dyalog APL, you cannot know the syntactic role of a name until run time.
 
9:54 AM
<moon-child> parsing can't go left-to-right. Otherwise how would you handle 5+x←2
 
Kap is a strict left-to-right parser, and it has no problems handling 5+x←2. What is the question?
 
So KAP looks ahead to the right?
 
It's a left-to-right recursive descent parser. When it finds the leftarrow it looks at the left-side arguments (which is simply a variable reference to x. It unwraps that reference to find the symbol name x and replaces it with an assignment).
 
<moon-child> bad example. Better is: x+x←2. When you see 'x' on the left, you don't know its syntactic class until you get to the 'x←2'
 
@Adám Yes, but that is not important in the assignment case.
This is where the left arguments to assignment is processed: github.com/lokedhs/array/blob/master/array/src/commonMain/…
 
9:57 AM
<moon-child> @EliasMårtenson take a look at jsoftware.com/help/dictionary/dicte.htm. (In that example it evaluates right away instead of building a parse tree for later, but you don't have to do that to use the same technique)
 
I have to read the article in detail, but at first glance that looks like it processes all the tokens first, then parses it right-to-left?
KAP only ever does a single token lookahead.
 
@EliasMårtenson That would be the same as in Dyalog.
 
@Adám That explains things.
OK, I have to think about this. I'm considering dropping the idea of supporting this syntax, and only ever use ∇ for function assignment.
I still want a way to do declare simple functions without explicit argument names though (which is whta ∇ does).
Maybe something like: ∇ foo ← {1+⍵}
I don't know. That's ugly too. I'm actually terrible with user interface design (and syntax is a kind of user interface)
 
How does KAP handle x+x←2 and y[y←0 1]? (I know it does handle them, but I don't understand how it can.)
@EliasMårtenson Do you have recursion in KAP?
 
<moon-child> @EliasMårtenson obviously do what you think is best, but I think you'd be better served by giving up on the one-token-lookahead parser. It sounds a bit like the lexer hack in c, where a by using a technically more complicated parser (in that case, not context-free), you actually simplify matters substantially
 
10:27 AM
@Adám Yes, there is recursion of course.
@Adám It's (small) hack, actually. When parsing a strand, it keeps a list of Instruction instances (an Instruction is merely an object that can be evaluated to yield a value). When it comes across a function, it gathers up all the collected values (it's a member called leftArgs in the class APLParser), then recursively calls the parse function again to collect the right-side arguments.
When recursing, the leftArgs is again empty and it starts to collect Instruction instances again.
Now, a plain number results in an Instruction subclass called LiteralNumber.
A function invocation instruction is called FunctionCall1Arg or FunctionCall2Arg.
A variable reference is called VariableRef.
Now, if the parser sees a left-arrow, it looks at leftArgs to check what it is. If it contains a single element, and that element is of type VariableRef, then the element is removed tom leftArgs and replaced with a an Instruction instance of type AssignmentInstruction.
It's created by digging into the VariableRef instance to retrieve the name of the variable.
With this information, you should be able to follow the code that handles this: github.com/lokedhs/array/blob/master/array/src/commonMain/…
Oh, and if you're asking about LiteralScalarValue, it's what is returned from (foo). I.e. 1 is a LiteralNumber, while (1) i a LiteralScalarValue that contains a LiteralNumber.
I guess I could handle (x) ← y like x ← ⊃y. I guess that would be consistent. If I wanted to do that, I'd decide based on whether the left side argument is a LiteralScalarValue
@DyalogAPL I think making significant changes to the parser to deal with this particular case is not ideal. By forcing the use of a one-token-lookahead left-to-right parser, the parsing rules becomes very easy to understand and less likely to create confusion.
 
 
2 hours later…
ngn
12:20 PM
@EliasMårtenson strictly speaking dyalog doesn't parse. at "fix" time (what we would normally call "compile time") it tokenizes left-to-right and does a small amount of other work, like preparing strand fragments or adding pointers between matching brackets. the final decisions about the tree of function applications are taken at runtime, when the kinds ("nameclasses") of variables are known (there's no actual ast in memory, just a conceptual "tree"). this goes right-to-left with minimal look-ahead.
(if marshall contradicts any of ^, he's probably right)
@EliasMårtenson do you build an ast in kap? if you want to infer the kinds at compile time, why don't you add a separate pass?
@EliasMårtenson do you call that bytecode or classcode/instancecode? :)
 
12:41 PM
@ngn Good question. I guess instancecode is the closest :-)
@ngn Well, the resulting instance structure is essentially a parse tree, although it's an executable tree so it's a bit more complex than just a regular parse tree.
However, optimisations can be done on this structure if needed.
 
ngn
@EliasMårtenson here's an interesting case. would kap be able to parse f←{g⍵} ⋄ g←{f⍵} and infer that both f and g are functions?
 
1:00 PM
@EliasMårtenson What is the syntax for a function to call itself?
 
1:15 PM
@Adám The name of the function: Infinite loop that calls itself: ∇ foo (x) { foo 1+x }
And no, unnamed functions cannot call themselves directly at the moment, simply because I don't have a syntax for it. I know Dyalog uses ∇ but that's not available. So either I change the syntax for function definition, or I use a different symbol.
@ngn No. It requires functions to be forward-declared.
However, you can mimic it using function values (first class function values)
 
2:00 PM
@ngn is that how ngn/apl parses, too?
 
@EliasMårtenson In my experience many pure mathmos count from zero, many applied mathmos from 1.
 
@xpqz ngn/apl compiles ahead-of-time
 
Is there a formal grammar for apl knocking about somewhere?
 
ngn
@xpqz no, ngn/k tries to do more work at compile time. first it builds a half-done ast in which sequences of nouns and verbs are flat. then it walks the ast and infers the kind of every node (kind:noun|verb|adverb|conjunction or if you prefer array|func|mop|dop). variables have static kinds, you can't have things like a←0⋄a←{}. so, using the inferred kinds, it goes through the tree again and determines what the tree structure of noun-verb sequences should be.
then this gets compiled to something like bytecode (apart from bytes, it might contain js function objects but that's just due to my lack of at the time..), and interpreted
*lack of experience
 
@xpqz that's kind of hard to do (e.g. see 2 (⍎(?2)⊃'2+') 2)
there is a grammar of BQN though
 
ngn
2:10 PM
@dzaima if you allow ⍎ to return functions, all bets are off
another enemy of parsing is ⍺←⊢
 
@dzaima but if you restrict yourself to normal functions/operators and strands and no variables (let's not think about assignment as that's very different in every impl), making a grammar isn't that hard (but still, rather pointless)
 
One day I might try to make my own. Seems to be a rite of passage around here :)
 
ngn
@xpqz "what i cannot create, i do not understand" -feynman
 
2:34 PM
@xpqz I think the table of binding strengths fully defines the grammar (assuming you know which symbols are in which class). See also this
@xpqz I've never attempted to write an APL interpreter of any sort. It seems such an unnatural thing to me. Probably because APL is a native language to me. otoh, I've written quite a few interpreters and transpilers for other languages ― in APL.
 
2:52 PM
@EliasMårtenson in case I didn't show this to you - dzaima/APL's parser debug info (which, if ignoring brackets & schizophrenic slashes, seems to act very equivalently to Dyalog's)
 
@Adám I think implementing a language imparts a deep level of understanding. But first I'm going to write a beginner's intro to APL I wish I'd had when I started.
 
@EliasMårtenson Since the prefix for a function is the new thing, why not use for recursion and another symbol for declaration, e.g. ƒ (iirc, this is what VisualAPL did).
@xpqz Excellent. I'm looking forward to seeing that.
 
@Adám Very good point, and my thinking in the last few hours have steered towards this as well.
I've considered using defun just like Lisp. Since I've taken so many other ideas from Lisp.
 
@xpqz Hey look, a formal VisualAPL grammar!
 
ngn
@xpqz which language do you want to implement apl in?
 
3:06 PM
@Adám my ip is permanently banned \o/
 
ngn
@Adám 56 pages! :O
 
@dzaima I can email it if you really want it.
 
@Adám nah i got it
 
3:25 PM
@ngn I'd probably reach for Racket (Scheme), for the love of everything lisp-like.
 
ngn
@xpqz cool :)
 
One vintage language in another :)
 
ngn
@xpqz does racket support vectors and arithmetic on them?
 
Yeah.
It has a nice nd-array module.
Not used it in anger. But said to be pretty quick.
 
@xpqz You may want to take a look at April as well, which is an APL implemented in Common Lisp.
If for no other reason to get an idea of the approaches taken there.
 
3:36 PM
@EliasMårtenson yes, I've been poking around with April a bit.
 
@Adám What syntax do you suggest? Nothing that there are two separate ways of declaring functions that I want to support: one where arguments are explicitly named, currently using the following syntax:
∇ (a0;a1;a2) foo (b0;b1) { a1+a1+a2+b0+b1 }
and then I also want to support a very terse form, where arguments are ⍺ and ⍵.
 
@EliasMårtenson Can i get back 2 u?
 
It's the latter where I can't use foo←{text}
 
@EliasMårtenson is anything preventing those just being ƒ left name right {body} and ƒ name {body}?
 
@Adám Of course. This is a hobby project. No deadlines.
 
3:39 PM
i have a deadline in 5
 
@dzaima Well, I have considered that. However, I also need to support niladic functions.
 
@EliasMårtenson ah. my suggestion would be: don't :)
 
ngn
^ +1
 
@dzaima I don't right now, because the parsing rules are messy.
 
@dzaima (fwiw chromium devtools format (function abc(){}) as ƒ abc(){} (and unnamed just don't have the name))
 
3:41 PM
I think the key thing I'm collecting suggestions about now is what "f" should be :-)
 
ngn
@EliasMårtenson if you're going to support {⍺⍵} anyway, why do you need other syntax for defining functions?
 
@ngn because assigning them is impossible with
 
ngn
@dzaima well, then shouldn't that be fixed?
 
@ngn 1) that's afaict hard; 2) there's not really that much benefit to reusing the syntax other than not introducing more syntax
 
Hm, seems like I don't understand aspects of APL scoping rules...
I have a bug where assigning a value to a variable doesn't "write-through" to a dfn later
Yesterday I was talking with @Adám about dfns being lazy and tacit fns being eager, in a sense, but now dfns betray me too :D
 
3:52 PM
@MartinJaniczek so something like a←0 ⋄ {a←1}0 ⋄ a?
 
Probably. In my mind that would result in 1, not 0
which is not what Dyalog APL does, hmm
 
@MartinJaniczek you want to do a⊢←1 then
 
Can you explain this to me?
 
@MartinJaniczek it creates a new local variable instead of mutating an outside one. When you're doing modified assignment, though, it's forced to mutate the value outside
@dzaima there isn't special, it just uses the same syntax that a+←1 does. (and, of course, a←0 ⋄ {a+←1}0 ⋄ a also gives 1)
 
@dzaima It indeed helped, thanks a bunch! And I learned something :)
Didn't expect this locality inside dfns
 
3:57 PM
reasoning for this being that by default you don't want to accidentally be mutating outside state if variable names happen to clash
 
I was almost considering doing a "clean" FP style where I just pass everything explicitly ...
 
@ngn Because Kap supports multiple arguments to a function.
 
@MartinJaniczek fwiw iirc dfns were initially supposed to be a more "FP" alternative to tradfns
 
So I don't have a better syntax for something like: foo (arg1 ; arg2 ; arg3)
 
@dzaima They do feel that way, there's just the rest of the language being mutation-heavy that betrays that
But as a concise lambda syntax, why not!
 
ngn
4:03 PM
@EliasMårtenson it could still have been something lambda-like, for instance {[arg1;arg2;arg3] ..}
i like lambdas. they are expressions. they can be used in other expressions.
 
4:19 PM
@ngn I have that. But lambdas are first-class functions and are values in their own right. you can do foo ← λ{⍵+1}
but note that foo 1 in this case is an array of two values: the function and the value 1.
 
ngn
@EliasMårtenson what i don't understand is why use one style for ≤2 args and completely different style for ≥3?
 
@EliasMårtenson is that an actual 3-arg function or just destructuring of the right arg?
 
@dzaima A little bit of both. Yes, it's destructuring. But it's not destructuring an array. It's working on what is called a "list". It has the following syntax: a ; b ; c ; d.
So a multi-argument function works by destructuring a list, not an array.
 
ngn
"list"? what..
 
^; i'll add with a "why"
 
4:24 PM
At the same time, the axis argument in something like foo[0;1;2] is simply a list too.
The idea is to normalise the otherwise odd syntactic array[index;index;index] in APL
 
@EliasMårtenson I'd prefer to get rid of it but ¯\_(ツ)_/¯
 
if index;index;index was simply a single value, then there would be no need for special parsing.
Point is, people don't have to think about it, since default behaviour is APL compatible.
 
; in [] is approximately as special as in {}
 
@dzaima VALUE ERROR
 
@DyalogAPL ಠ_ಠ
 
4:26 PM
@dzaima In APL yes. Not in kap
 
at the very least I would not call it a "list". that is explicitly asking for confusion
 
In kap, you can do foo ← (1;2;3). The value of foo is now a scalar value which is a list (better name would be N-tuple) of 3 values.
Yeah, N-tuple is a better name I think?
 
@EliasMårtenson i guess
 
ngn
@EliasMårtenson how is that different from a 3-vector?
can you do (1;2)+(3;4) to get (4;6)?
 
@ngn just as much as a dictionary is different from a vector i guess
 
4:29 PM
@ngn No. As I said, N-tuples are scalars. You can't do much with it other than destructure it.
 
ngn
got it
 
But the biggest difference is in its parsing rules. It has lower precedence than any regular APL functions.
so 1+2 ; 3+4 ; 5 is a 3-tuple of values 3, 7 and 5.
This makes parsing compatible with array index notation in APL.
I thank you all for these discussions. Thanks to very astute observations from all of you, I have managed to implement several very good improvements.
You have to recall that one of the design criterions for KAP is that it should be possible to write code which is imperatibe and reasonably recognisable to people without APL experience. Sort of like a wa to get non-APL'ers interested by easiing them into it. A syntax where multi argument functions can be called with syntax foo (a;b;c;d) helps here I think.
 
@EliasMårtenson that could just as well be done with foo (a b c d) and regular vector destructuring though
 
@dzaima Not quote. For example, foo (1+2 3+4) would give surprising results to the beginner.
 
@EliasMårtenson I don't think that'd be that big of a problem
 
4:40 PM
@dzaima To you or me (or in fact anyone else on this channel) I agree with you.
But I have the tutorial that I intend to write in mind.
 
or you could make a proper vector notation to use in place of strands
 
@dzaima Very true. But then I would be remaking R. :-)
What I really wanted to do was to fulfil three goals of mine: 1) Make an APL, 2) Change some things that I dislike about APL. ⎕IO being one of them, and 3) Make it possible for beginners in particular to write imperative code if they can't think of a nice array based solution.
The last is to encourage beginners to write actual software and not juts playing around.
 
also with headers, ƒ foo (a b c d) {(a+b)-c+d} vs foo←{∇a b c d: (a+b)-c+d} isn't that bad either (and teaching that is quite simple - regular assignment, is recursion and thing before : is a sort of self-description of how to call itself)
 
ngn
@EliasMårtenson imperative is not the opposite of array-based
 
@ngn We may use different terminology, but I hope you see what I mean.
@dzaima You are absolutely right, and I'm open (nay, committed) to changing the function declaration syntax. And I'm absorbing all the ideas I get from you.
 
4:46 PM
@dzaima (though i guess : might not work if there are guards)
 
ngn
@EliasMårtenson the opposite of "imperative" is "declarative". for the opposite of "array-based", i suggest the scientific term "loopy" :)
 
@ngn i'd guess more specific would be "branchy"
 
ngn
@dzaima i'm not sure what you mean
even pure array code can make use of some branching
 
@ngn in converting JS/C/Java to APL, ¨ takes care of 99% of loops. But translating ifs is often much more painful
 
ngn
@dzaima because apl has guards instead of the more general cond?
 
4:53 PM
@ngn that mostly, but even cond is, imo, very ugly
 
ngn
right, it should be used sparingly. so we agree :)
 
@ngn it should be used sparingly doesn't work if you explicitly want to allow it
 
@dzaima Kap has both if and while, both implemented in the library using defsyntax. That's one of the main features I'm hoping will make simple code easier to deal with.
 
as far as i'm concerned, if/else just doesn't work with APL syntax. You either just don't have it (and make it painful to write certain type of code), or have a different syntax for it (tradfn :-things, KAP's predefined macros)
 
 
1 hour later…
6:03 PM
Arguably one more purpose of KAP is for me to have a platform on which to experiment with these things.
Not just me, a lot of the things I've experimented with comes from you.
 
 
2 hours later…
7:52 PM
I wish you could use guards in parentheses too - (cond: foo ⋄ cond2: bar ⋄ baz)
 
@user that's a nice idea, though it breaks proposed namespace literals - (key1:value1 ⋄ key2:value2)
 
@dzaima Oh, that's too bad. What are namespace literals? Are they like JS's object literals?
 
@user same idea, yeah. (dzaima/APL has them)
as a short-hand alternative for m←⎕NS⍬ ⋄ m.a←2+2 ⋄ m.b←3
 
Cool!
 
(part of Array Notation)
 
 
2 hours later…
9:43 PM
<moon-child> @user my apl does support separators in parens (e.g. (foo⋄bar⋄baz) ←→ ((foo)⊢(bar)⊢(baz))). But guards don't really make sense there; what if you have a guard inside of a set of parens inside of a dfn?
<moon-child> or, for that matter, nested parens
<moon-child> (my notation also conflicts with the proposed array notation; but I prefer it this way for consistency. May reconsider later)
 
 
2 hours later…
11:43 PM
@Moonchild The same as nested if-else statements in other languages, I guess
Like {⍵>3:(⍺=⍵:⍺ ⋄ ⍵) ⋄ ⍺=⍵: ⍵ ⋄ ⍺} instead of something weird like {⍵>3: ⍺{⍺=⍵:⍺ ⋄ ⍵}⍵ ⋄ ⍺=⍵: ⍵ ⋄ ⍺}
 

« first day (1437 days earlier)      last day (1218 days later) »