« first day (1364 days earlier)      last day (43 days later) » 

8:13 AM
A: Sandbox for Proposed Challenges

RGSWhat valence does this APL train have? code-golf sequence decision-problem apl Context In APL, trains are tacit sequences of monadic/dyadic functions that can be called with one or two arguments. We'll code something to check if a given train follows the correct structure we need in order to have...

I'm about to post this APL-related challenge to the main site. If anyone has any last comments to make, now is the time :)
8:27 AM
@RGS Maybe cross-post in TNB?
@RGS You could consider a recursive definition (too).
@Adám That is true and tbh it was how I understood the structure of trains in the first place... But I think providing one correct algorithm suffices. Would you agree?
Sure, it was just an idea.
Thanks :)
Btw if anyone here speaks Portuguese and is really really interested, I can get you a "seat" in the 2nd part of my "Learn APL with neural nets" workshop... Except if you are reading this you probably know "too much" APL for the rhythm of the workshop.
8:42 AM
Haven't seen J.Sallé for a while…
@RGS I'm writing a solution, so hold for a while if you want me to check your examples.
@Adám Alright, I can wait for a bit ofc.
@RGS Maybe add a couple of longer valid trains?
@Adám in particular, valid monadic trains, no? I am having a hard time coming up with interesting long dyadic trains
@RGS MDBBBBDB is an interesting long dyadic train.
Here's the 5 new example trains,
in the second line of `t`:
9:20 AM
@RGS Can you reorder the examples so the results are lexicographical?
As in a dictionary, or with same lengths grouped? (I'm assuming you are talking about the trains)
@RGS No, the results. First all the 0 0s, then all the 0 1s then all the 1 0s then all the 1 1. Secondary sorting doesn't really matter.
@Adám Done
9:39 AM
@RGS OK, I have a reference solution (not very APLy) that matches your results.
Alright, it is time to post it, then
Q: What valence does this APL train have?

RGSContext In APL, trains are tacit sequences of monadic/dyadic functions that can be called with one or two arguments. We'll code something to check if a given train follows the correct structure we need in order to have a sound train. Task Given the sequence of function arities in the train, deter...

1 hour later…
11:08 AM
OK, I have implemented hashmaps in a somewhat silly, but straightforward way. I'd like someone to critique the design.
Basically, you create a map using the following m ← map 3 2 ⍴ "key" "value" "key2" 1 :key3 (1 2 3)
In other words, the argument is a two-column array with key/value pairs.
Since KAP values are immutable, updating a value returns a new map: m ← m mapPut :key4 "new value"
Getting a value is done like this: m mapGet :key4
"I'd like someone to critique the design" - you've come to the right place :D
Finally, if the right argument to mapGet is an array, the call returns an array of the same dimension with the respective values in each cell: m mapGet 2 2 ⍴ "key" :key3 :key3 :key3
@ngn Yeah, that's what I was hoping.
There is a mapRemove as well that does what you'd expect.
Oh, and the map is ordered. That way you can convert the entire thing into an array if you want.
Finally, the names beginning with a colon, like :foo are keywords. They are basically symbols in the exact same way as they work in Lisp.
Arrays can also be used as keys in the hashmap. Equivalence is the same as ≡
11:24 AM
immutability - great!
2-column - why not a pair of nested arrays: (keys values)? this way the keys and values can separately benefit from more compact representation.
if keys and values are separate vectors, you could also reuse your dyadic iota impl to search in the keys
"hash"maps - is there any actual hashing involved in this (or planned to be)?
right, that's a big problem with immutable maps - getting them to use hashing well is pretty hard
(at least without refcounts you're back to O(n) mutation, and without a proper data structure you're stuck with O(log n) reading)
12:02 PM
@dzaima Well, I'm actually deferring the implementation of the immutable hashmap to an external library. It's not super fast, but acceptable for now. Adding 10 million elements to it one-by-one in native (non-KAP) code took about 5 seconds on my reasonably fast Ryzen workstation.
KAP itself is not super fast, and when I do the same loop in KAP itself, the hash map management is 40% of the total time spent. (so about 12 seconds total)
ah right, completely forgot HAMTs existed. still, it's quite suboptimal performance
Thing is, I expect most uses of hashmaps to come from lower level calls, such as loading a JSON file.
(JSON output is encoded as hashmaps)
@ngn When you say separate vectors, are you suggesting that adding three key-value pairs should look something like this? m mapPut (:key1 :key2 :key3) ("value1" "value2" "value3")
@EliasMårtenson ah, ngn was talking about storage of the hashmaps, whereas you already use some native thing
@EliasMårtenson i meant map creation, but yes, mapPut could do that too
@ngn Yeah, creation and putting should have the same format, or there wil be confusion :-)
I'm calling into this library for the immutable map: github.com/Kotlin/kotlinx.collections.immutable
12:09 PM
@EliasMårtenson are you trying to create a fast language at all?
or is it one of those "expressive syntax" languages
12:44 PM
doing some project euler problems in APL, it's a bit annoying having to implement my own multiplication for problems involving large numbers, does APL have any libraries that support infinite precision integers?
@rak1507 dfns.big
Oh well that makes life easy, thank you
1:36 PM
@user870903 phantomics You should have write access now.
@ngn Speed is not a primary concern. However, faster is always better so I do regular profiling runs to see where time is spent.
How can I use dfns.big with +.×
@rak1507 what argument ranks are you looking to have?
I'm looking to do something like this +.×⍣100⍨⊢2 2⍴1 1 1 0
(i'd guess your best bet would be to reimplement it using pure addition & multiplication)
ah, so proper matrices
1:49 PM
@rak1507 Can you not simply do +big.(×big)⍨ ?
I don't think so
ah right, that also works
Hang on
That does work
I swear I tried that....
note that it's pretty slow (yes, 3000x slower than dzaima/BQN)
So slow I gave up using that and implemented my own which worked better
Using a non matrix method worked better for the problem anyway
2:02 PM
as @Adám said, keep things flat if you want it to run in reasonable time
@Razetime bigints in a flat format really isn't a thing
Was talking about "non-matrix method"
Generally the matrix method for fibonacci runs very fast, but here it was slower than using my own crappy addition for big numbers + a flat array
Is there a smarter way of doing ↓⌽↑⌽¨⍺⍵? Left pad with 0s
Design question: What would be a better way to represent a JSON map (i.e. an "object") in APL? I'm using a hashmap now, but arguably I could use some kind of array (2-column?) instead. The code to access a given (or multiple) elements should be easy.
2:12 PM
@rak1507 {⍵↑⍨¨-⌈/≢¨⍵} may be faster.
@EliasMårtenson depends on what it's used for - a map is arguably better for ease-of-use, but some matrix form (e.g. what Dyalog does with ⎕XML) might be more performant
@dzaima And ⎕JSON
@dzaima Performance isn't a priority here, as long as it's not terrible.
@Adám ⎕JSON just uses namespaces
@Adám Do you have a link to Dyalog's documentation? Perhaps I should use a similar format to make porting easier?
@dzaima Oh, that won't be compatible.
2:14 PM
@EliasMårtenson Just search APLcart for ⎕JSON and click (?)
or do ]help ⎕json in Dyalog
Or ⎕JSON and press F1
oh, there is a matrix JSON format
I wish aplcart didn't have dark background. I struggle to use sites that do (heave astigmatism, everything starts spinning if I look at dark background for more than a few seconds)
@EliasMårtenson Click the contrast symbol in the bottom right.
2:16 PM
@Adám wow. Thank you! I never thought of looking there. You're saving my eyes :-)
@EliasMårtenson You can bookmark aplcart.info?w
(i'll assume you've already changed the theme on my paste)
@Adám I found a bug though. If I click on a function, it opens the view where you can type code. That one forgets my colour choice, and there is no button to change.
@EliasMårtenson :-DDD That's a different site altogether and has nothing to do with me.
@EliasMårtenson getting a userscript/userstyle for TIO shouldn't be very hard
2:22 PM
@Adám Oh wow. Yeah, I see that now. Sorry.
So I tried the format style M for ⎕JSON. I'm not sure I understand how that one is supposed to be used.
@EliasMårtenson i'd personally say it's not supposed to be easy to use:p
@dzaima Fair enough. I'm quite convinced that I'm not going to use that as the primary format. Sorry Dyalog.
@EliasMårtenson the code to access elements is up to you. how about m[k] instead of m mapGet k?
@ngn Hmm... Not a terrible idea.
I mean, it'd be trivial to do.
Hmm, I really can't find any reason not to :-)
@EliasMårtenson but remember that (1 2)(3 4)[1] is ⊂1 2
so either you have that as special syntax, or have the result be enclosed (what about multiple key access?)
2:35 PM
@dzaima Interesting you should say that, as mapGet also returns enclosed results.
@EliasMårtenson ah well there you have it
sucks that there is no function that, given an array and a position in it just gives the item at that position
(⊂⍺)⊃⍵ (or ⊂⍛⊃ with reverse compose) is the closest
so there'd be an argument for allowing (⊂:key1)⊃map to access a single key, unenclosed
Interesting point. I'll implement the basics first and add such functionality once I discover it's needed :-)
@dzaima Yeah, I guess both and have the same issue.
I'm building some examples, and a program that extracts information from a webservice is a useful way to show off the HTTP and JSON libraries.
@Adám yeah. (furthermore i believe dyadic with a vector left argument is stupid, and i've thought about making it just be the "access element at ⍺" function)
2:40 PM
@dzaima Exactly. Both and try to be too general and end up being awkward in the 99% case.
the problem with most things trying to be too general
@dzaima Why not introduce a new function for it? I propose ↖
@EliasMårtenson that's another character. my keyboard layout is already full :/
(though i suppose it does have and , both of which dzaima/APL doesn't have and are there just for Extended)
I have only extended the character set with one new char outside default APL, so I still have some free space :-)
I still copy paste symbols every time I program in any APL that isn't dyalog regular
2:43 PM
@dzaima None of them looks like a good representation of picking a value from an array though.
@EliasMårtenson no, i meant that as that i can free up some space. Of course they're bad for that
@rak1507 Then you'll love KAP, since it comes with a GUI and editor with a keymap :-)
Sounds useful
Either the diagonal one or perhaps ↰?
@EliasMårtenson I've used for a saner but really that should be the saner and another symbol the saner
2:45 PM
maybe ?
@dzaima ninja'd.
BQN uses and for indexing for some weird reason, but we can just use
If you want a better ⌷, then what about ⊡ or ⊟?
The difference between maps and arrays is that with maps any array can be a key, so it's fundamentally impossible for a function to distinguish between one key and an array of keys.
@Marshall so you have separate functions for one key and an array of keys.
2:48 PM
@Marshall Yeah, true. That's why my implementation forces you to enclose an array key: m mapGet ⊂"foo"
Extended & dzaima already have for the array of keys case, but a single-key case would be good
@dzaima In which case, why not just have a single-key function and use each-right for the multi-key version?
@Marshall because a multi-key function is very very useful for array access too
Or bind-each if you don't want to introduce each-right. Might require an extra set of parentheses, but that's all.
while of course we could always use each-right, it's kind of stupid that the most simplest form of accessing arrays in an APLy manner (i.e. with a vector of positions) takes a whole two chars in a language about arrays
(also dzaima/APL just doesn't care about the fact that should be iterating over the left argument and does the actually useful thing with a map right arg)
2:52 PM
But a vector of positions is much better suited to cell selection, which has no equivalent for maps.
@Adám I think it might be useful changing the error message in dfns.big from 'Eh?' to something more descriptive
@Marshall it could have an equivalent if we allow the keys to have rank >1
@Marshall i think it's worth forgetting about that and just make it select element always
(that's what dzaima/APL does. Still haven't felt the need of this whole cell business)
@dzaima Putting different functions together like that closes off some design space: for example, if you use a map with vector keys to implement a sparse array then you'll have to change your code.
@dzaima example, plus ⎕VI←1 for those thinking a bunch of 2-item vectors is stupid (which it most definitely is)
@dzaima (i'm actually not quite sure of the implications of ⎕VI←1 on map accesses)
@Marshall why? "a" "bc" ≡ (1 1)(1 2)⊇(1 1:"a"⋄1 2:"bc") should work
@dzaima (obviously not in dzaima/APL as i don't have arbitrary keys, though there's nothing preventing me from adding them)
3:00 PM
@dzaima How does it know (1 1)(1 2) can't be a key?
@Marshall why would it need to know? always returns an array with the shape of its left argument, and always accesses the items of its right argument by the left argument's elements
Oh, you switched functions on me.
So is consistent but isn't? But array couldn't be translated to maps anyway, right?
@Marshall is stupid and pointless, that's what it is
(and this is me rebelling against the stupidity of . Still want to make 1 1⊃a be ⊃1 1⌷a)
right, a problem with being both "get item with key ⍺" and "get item at position ⍺" is that could be , in which case it could both be "disclose" and "get item with key ⍬", which do different things on a map argument
@dzaima If KAP maps are atoms, which are different from simple scalars, then it won't have this problem.
3:21 PM
@rak1507 I agree. I'm hoping to put dfns.dws on GitHub soon so people can PR…
@Adám Can you help me better understand what type of work that entails?
@RGS Sure. Wanna meet about it?
@Adám Give me a call?
4:00 PM
started at opposite end of problem last night, and started porting the bqn primitives to erlang.
got partway thru group_ord.
5 hours later…
8:51 PM
Just scraped the APL Orchard's transcript (just what's gettable from from the main transcript pages, so no precise dates nor original markdown) just so i'd be able to have a sane way to search things :D
@dzaima why transcript and not through the api?
@ngn afaik there isn't a chat api
9:07 PM
there is a chat search; is it not good?
@TessellatingHeckler you can't search for APL characters
for example, this is the first occurence of (so it didn't make it to 17.0, huh)
@dzaima there is, if you press f12 and study the xhr-s
@ngn oh, of the "load older messages"? i guess that would've been slightly better (giving 100 messages/invocation compared to my ~95) but it still only gives the html
oh, it also has a precise timestamp
oh, you can choose to ask for more messages (appears it caps at 500 though). ¯\_(ツ)_/¯
9:25 PM
@dzaima you can get them all with multiple requests
@ngn well of course. probably would've done this, but utilizing that obscure button didn't occur to me
fair enough
9:42 PM
It's interesting looking back on my old solutions to problems in APL and seeing how differently I'd do things now, I wonder if in 3 months from now I'll be saying the same things about my current way of thinking
@rak1507 as long as you are evolving, yes
10:08 PM
I find the BQN javascript code pops something off the stack, calls set() on it, and the javascript environment variable e changes. Vaguely remember reading that they share variables
@TessellatingHeckler set indeed sets things in the environment
and a LOCM=22 instruction beforehand is what gives set the environment to modify
LOCM sort of creates a reference to an item/variable in an environment. set then assigns to that reference
@dzaima It's voodoo, I'm sure. I can see case 22 pushes an [env,index] pair onto the stack
@TessellatingHeckler in the more recent JS interpreter it uses {e:env,p:index} actually. It's just a pair of the array to mutate, and the index where to.
I get 37 instructions into building the runtime until my code deviates, the environment variable isn't changed when the set() runs. 21x of those are function-push, I think there are 2x LOCM in that time.
@dzaima so don't be confused that it's an array (as that's just an implementation detail). It's a completely separate type of thing
10:21 PM
apart from being confused by everything, the env/pointer isn't so confusing, it's the way the nested array taken out of [e[0], 3] still updates e when it's changed that is surprising
@TessellatingHeckler e[0]?
How did two people end up trying to implement the BQN VM in languages with default immutable arrays?
Seems you're supposed to use .Net's ArrayList for mutable arrays.
PS/.Net arrays are mutable, and PS bodges them so they are extendable (slowly)
Okay, that's just lies on the internet then.
.Net arrays can't grow or shrink, but you can change what's in them. They picked the less useful kind of immutability. Everyone wants to use them like Python lists and .append() so the default recommendation is to use ArrayLists instead
if you have a wide screen you can see the JS code on the right as comments
the reason I went this way is to make it as close as a literal line-for-line translation as I could, because I don't understand BQN or JS or VMs or C# enough to deviate significantly from scratch; having two line-for-line copies in two languages with REPLs/consoles has been incredibly helpful for working through comparing behaviours
10:28 PM
$e[$i] in ge should be $e[1].
and having something similarly high-level, too
@Marshall ! thank you!
not sure if that was sarcastic, but
PS D:\> $a=@(1,2,3); $a[1]=55; $a
they really are
Does anyone know why {(b e m)←⍵ ⋄ {m|⍺×m|⍵×⍵}/b*⌽0,2⊥⍣¯1⊢e}2 7830 1E10 returns 0? (modular exponentiation)
I set ⎕PP to 20
Is there some sort of floating point stuff going on? :/
PS being able to embed/use C# types should give me a way to switch out parts of this incrementally
@TessellatingHeckler No, there are definitely lies on the internet because I can find statements that they're immutable and statements that they aren't.
But to test for mutability you need to make a copy of a and see if that changes when you change a.
@rak1507 there is. One of the intermediate answers is 3411158016, which you square, getting 1.1635999010121056E19, but FP starts dying at ~1E16
10:36 PM
Ahh, makes sense, thank you
⎕FR←1287 fixes it, but will fail for bigger modulos for obvious reasons
@Marshall I can take a reference to a $b=$a and changes to $a show up in $b. If I take a copy then surely wouldn't show changes because it's a copy?
@TessellatingHeckler I meant reference; I would usually call the thing you're calling a "copy" a "clone".
I always forget about ⎕FR, thanks :)

« first day (1364 days earlier)      last day (43 days later) »