1:52 AM
@rak1507 donee

4 hours later…
5:56 AM
@ngn mine uses erroring/not-erroring to distinguish between truthy/non-truthy inputs (i didn't say 'respectively'). okay, 500 rep for a solution <8b in vanilla
(and of course, the bounty's open to everyone)

6:36 AM
I am considering implementing fork (i.e. `A (FN1 FN2 FN3) B`) in Kap. I have noted that if I support that, I can delay having to do full-fledged flow analysis of functions and still be able optimise several types of functions.
Would it be too much to ask for a handful of small testcases for forks? I don't usually use them myself when programming, so I'm not sure I'll be able to catch any edge cases once I complete the implementation.

7:11 AM
@EliasMårtenson All the combos of using `⊣` and `,` and `⊢` should do the trick.

As in ⊣,⊢ and ⊢⊣, ,⊢⊣ etc?

Yes:

<moon-child> just ⊢,⊢ ⊢,⊣

`{⍎2⌽')21(','⊣,⊢'[b⊤⍵]}¨⍳×/b←3⍴3`

<moon-child> ⊣,⊣ ⊣,⊢

7:15 AM
moon-child: No, one should check with `,` in the outer tines too, imo.

<moon-child> ah - fair enough

And what arguments should I use for testing? A=1 2 3 and B=4 5 6 would be enough?

7:39 AM
@EliasMårtenson I just showed you with 1 and 2. That should be plenty.

@Adám That's the next step. One at a time :-)

@EliasMårtenson What is monadic `⊣` in KAP?

2-trains and 3-trains should be called carriages, leaving the name "train" for a series of carriages :P

@Adám Identity. It's actually identical to monadic ⊢ at the moment. I was considering using it for "collapse" though (forcing evaluation of all lazy values)
Currently collapse is a full named function (called "comp" (for 'compress'))

@RGS I think the individual functions in the train are carriages.

7:43 AM
However, I ave also considered putting it on monadic =

@EliasMårtenson Note that implementations vary when it comes to monadic `⊣`. Dyalog uses `⊢` with APLX being `{0 0⍴0}` iirc, and GNU being `{}`

But then there is the function "defer", so perhaps I'll pick a pair of completely new symbols, because collapse and defer are opposites.

@EliasMårtenson Wouldn't monadic `⌷` ("materialise") be the obvious choice?
@EliasMårtenson What is "defer"?

@Adám An example may be helpful: `((defer println "foo") (defer println "bar"))[1]` prints "bar"

I thought "defer" was the default.

7:45 AM
It delays evaluation of a function call until the value is requested.
@Adám Not for regular function calls.
It was default for a while, but it turns out that in parctice it's almost never what you want, so I switched the default.

@EliasMårtenson it's like a custom control structure thing, not a regular function, right?

@dzaima It's a regular function.

@EliasMårtenson Looks like defer would be a monadic operator then. Essentially `⍰` as described here but without the threading aspect.
How can `defer` have an effect on `println`. APL order-of-execution dictates that `println "bar"` is evaluated before we even look at `defer`.

@Adám Sorry, yes. It's an operator.

@EliasMårtenson Then it has to go on the immediate right of `println`

7:49 AM
Yes, you're right. And that's how it works.

So `defer` and `collapse` form a monadic-operator/function pair much like `&` and `⎕TSYNC` in Dyalog.

@EliasMårtenson oh so it is `((println defer "foo") (println defer "bar"))[1]`. that makes more sense

I implemented in a month ago, and I never really used it much yet. Originally I wanted to implement it with the syntax I gave you, but while implementing it I realised that an operator made more sense.
@dzaima Yes, indeed.

@EliasMårtenson Unless you make another oddity like `∘.f` or make `defer` a dyadic operator with some sort of parameter as left operand.

7:52 AM
@EliasMårtenson Then I think `⍰` and `⌷` are good choices for "defer" and "collapse". `⌷((println⍰"foo") (println⍰"bar"))[1]`

You mean monadic ⌷? Hmm... And that's not planned to be used for anything in dyalog?

It is called materialise and is used to get the array consisting of the default property of an object.

@Adám Hmm... Sounds like a useful symbol for the function `mapToArray` :-)
(it takes a hashmap and returns a two-column array with keys/values)

8:06 AM
@Adám Is the thinking behind proposing ⌷ that it's a function that "picks out something"?

@EliasMårtenson Not really. Mostly just the fitting name "materialise" and it being a squished (per your "compress") version of `⎕`.

OK, makes sense. And I have no better suggestion so I think I'll go with that. As for ⍰, it seems to represent "something that maybe will be executed"

Exactly.

@EliasMårtenson I just remembered that that's what dzaima/APL does :D

Is ⍰ used by any other APL's? It's in the APL Unicode block, but I don't think I've ever seen it.

8:10 AM
@EliasMårtenson No, it has only been proposed as per the blog post I linked.

@dzaima (but i think making `⌷` be collapse makes more sense)

@EliasMårtenson Looks like defer would be a monadic operator then. Essentially `⍰` as described here but without the threading aspect.

It is indeed a monadic operator.

`⍰` looks operatory, imo. Like `⌸` and `⌺`.

8:12 AM
So Dyalog is getting it too? Are the semantics similar?

@EliasMårtenson I don't know if or when for Dyalog, but yeah, it'd be defer execution (in a separate thread) until jit.

I see
I have some ideas for threading myself, but I haven't settled on the details yet. I did some tests with automatic parallelism, and it works decently well thanks to the lazyness.

8:25 AM
@EliasMårtenson @dzaima It kind-of does that too:
```      ⎕USING←'System.Collections'
openWith←⎕NEW Hashtable
⍝ Add some elements to the hash table. There are no
⍝ duplicate keys, but some of the values are duplicates.
openWith
System.Collections.Hashtable
⌷openWith
System.Collections.DictionaryEntry  System.Collections.DictionaryEntry  System.Collections.DictionaryEntry  System.Collections.DictionaryEntry```

2 hours later…
10:11 AM
@Adám with 18.1⍺ and .NET Core 3.1:
`Linked: #.dict ←→ /Users/stefan/work/dyalog/AoCDyalog/src/dict`
:)
This is lining up to be one epic release.

@xpqz I'd be interested in a performance comparison between the APL-based class Morten pasted and the .NET Core based one.

Although using .NET from APL feels like strapping a caravan to a Ferrari.
@Adám I can have a go at that.

10:26 AM
@Adám morterns one doesn't use hashed arrays though right?

@rak1507 It is trivial to make it use them.

in that case the comparison would be interesting then

I added the 1500I thing to Morten's class.
So maybe adding 50k words as keys with a random int as the value, and then retrieving every key, summing the values might work as a perf test.

I just dicovered the best way to run Ride without having the keymap messed up.
Use Qubes OS and run Ride in a dedicated qube. The keymap thing will be localised to a single container.

10:47 AM
@Adám I don't quite get how the .NET hashtable indexing works in APL -- how do I get the value of a key? I can see all keys and all values correctly.
Had hoped I could do `ht['key']` but that errors.

try ht[⊂'key'] (just a guess)

Ah yes

11:34 AM
@MortenKromberg takes it:
```      WORDS←∪⊃⎕NGET'dictionary.txt'1
VALS←(⍴WORDS)?⍴WORDS
ORD←WORDS[VALS]
⍴WORDS
┌→────┐
│58110│
└~────┘
ht←⎕NEW Hashtable
{(k v)←⍵⋄ht[⊂k]←v}¨↓⍉↑WORDS VALS
z←⎕NEW Dict (WORDS VALS)
cmpx '+/ht[ORD]' '+/z[ORD]'
┌→───────────────────────────────────────────────────────────────────┐
↓  +/ht[ORD] → 3.0E¯1 |   0% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕│
│  +/z[ORD]  → 1.5E¯2 | -96% ⎕⎕                                      │
└────────────────────────────────────────────────────────────────────┘```
The way the constructor works for Morten's class, I excluded the creation from the timing, as it's a pretty unfair comparison.
I used:
```:Class Dict
:Field Public _keys←(1500⌶)⍬
:Field Public _values←⍬

:Property Keyed Default Item
:Access Public Instance
∇ r←get arg
∇
:EndProperty

∇ Make(keys values)
:Access Public
:Implements Constructor
(_keys _values)←keys values
∇
:EndClass```

12:31 PM
@xpqz `{(k v)←⍵⋄ht[⊂k]←v}¨↓⍉↑WORDS VALS``ht[WORDS]←VALS`

1:08 PM
Yes.

@xpqz With that change, is comparing creation time still unfair?

Less so, eyeballing, but can't get cmpx to work with just `cmpx 'z←⎕NEW Dict (WORDS VALS)' 'ht[WORDS]←VALS'`
Does it have to be a function call maybe.

@xpqz Oh, I think the assignment to `ht[WORDS]` doesn't return a result. Looks like a bug to me.

Hmm, no eye deer:
```cmpx 'z←⎕NEW Dict (WORDS VALS)' '{⍵[WORDS]←VALS⋄⍵}⎕NEW Hashtable'
SYNTAX ERROR
{0<⍵:∇ ⍵-1⊣{⍵[WORDS]←VALS ⋄ ⍵}⎕NEW Hashtable ⋄ ⎕AI}⍺```
I've never looked at Dyalog OO in any meaningful way, but I think Morten's class also needs a setter. Also, the constructor doesn't ensure that the keys are unique.
But still -- I think we can conclude that Dyalog's good at finding things in arrays, and that the 1500I hashing thing is competitive.
In other news: water wet. Sky up. Pope catholic.

1:29 PM
@xpqz Yeah, you could design the API for Dict to match that of Hashtable.
@xpqz Confirmed as bug. Logged as issue 18890.

@Adám These issue numbers, do they refer to an internal tracking system, or somehing that is visible to the public?
@Adám anyway, can't seem to benchmark that no matter what I try:
f←{h←⎕NEW Hashtable⋄h[WORDS]←VALS⋄h}
cmpx 'z←⎕NEW Dict (WORDS VALS)' 'x←f⍬'
EXCEPTION: Object reference not set to an instance of an object.

@xpqz Internal system, but allows me to find the right place to report when it is fixed.

1:52 PM
Do the issue numbers depend on ⎕IO?

:D

@rak1507 I don't know. The lowest-numbered issue is issue 3, and is clearly a test issue.

⎕IO←3?!

Looks like it.

That makes a lot of things more complicated.

1:56 PM
that's weird lol I wonder why they didn't start from 0/1

It could be that the first 2 or 3 issues didn't work out and were deleted from the DB.

ah that makes more sense
What was issue number 4 then, if that was the first real one

Someone reported that the input field of a grid object could be too large if the text in the cell was larger than the cell itself. However, we couldn't reproduce the issue, so it was closed.

When was that? Must have been a while ago

Not so long, Jan 2003. Apparently when we started using that big tracking software.
Then follows a bunch of supposed issues we either couldn't repro, or that were not actually an issue after all, and didn't require any changes.

2:01 PM
Haha, 'not so long'...
That's cool that there's a record of all the reports since then though

The first real issue is number 17. We're still working on that one… :-D

Mantis 17?

Yes, the infamous scoping issue.

I thought john scholes fixed that one

John thought so too. He mistakenly died.

2:06 PM
:(

Thanks for the link I think that's where I'd seen it before

So you're on bug 17/18890?
We'll be here a while!

No, thankfully, lots of later bugs have been fixed. Even issue 17 has was marked fixed on 2019-02-08, but various other issues have come up that trace their lineage back to it.

2:22 PM
I offer the following PR to @MortenKromberg's Dict class:
```∇ set arg
_keys ∪← ⊃arg.Indexers
_values ← (⍴_keys)↑_values
_values[_keys⍳⊃arg.Indexers]←arg.NewValue
∇```
My first Dyalog OO anything.

doesn't necessarily work for duplicates
because they don't line up

Need to fix the constructor, too.
To stop them from happening.

@rak1507 Right. One should use monadic `≠` on the keys to filter both keys and values.

the values don't have to be different
⍸≠keys to find unique, then index into keys and values
I think
(which assumes that if you have a conflict, you take the first one, but in other implementations it might be the last, if so ⍸⌽≠⌽keys)
would be a nice use for under I think

@rak1507 Why not use replicate?

2:28 PM
oh, that would make more sense

How do you deal with both existing and non-existing indexes in the same expression? You need to grow both keys and values arrays, potentially

@xpqz You could test for membership (the array is hashed, so it should be fast) and split the operation into two parts.

1 hour later…
3:41 PM
```        ∇ set arg;dedupe;unique;kk;vv;seen
⍝ Find the unique indexes and corresponding vals
unique ← ≠⊃arg.Indexers
kk ← unique/⊃arg.Indexers
vv ← unique/arg.NewValue

⍝ Separate out keys we already hold from new ones
seen ← kk∊_keys
(seen/_values)←seen/vv

⍝ Append new keys and corresponding values
_keys,←(~seen)/kk
_values,←(~seen)/vv
∇```
```z←⎕new Dict (('APL' 'Rocks!')(42 'Bob'))
z['APL' 'APL' 'odenkirk']←1 2 4```
^^ does what I think it should do.
Takes first on conflicts

@xpqz Looks nice. The last two lines can optionally be written together as `(keys values),←(~seen)∘/¨kk vv`

3

@xpqz It should be pointed out that they're not all bugs and they're not all associated with the interpreter. We use the system to keep track of the website, documentation, ideas, and internal changes to the build process.

@AndyS Ah yes, good point.

3:56 PM
@AndyS Heh. I know how it works... our bug tracking system is currently on ticket id 124,897...
@Adám hmm, I think my code has bugs.

4:11 PM
@xpqz Beware that the hashing is only maintained under ,← and ↓⍨←. If you use any other expression to modify the keys, you may need to redo the hashing:

R←1500⌶1 2 3
R,←4
1 (1500⌶)R ⍝Is R a hashed array?
1
V←10×R
(R V),←5 50
R V
1 2 3 4 5 10 20 30 40 50
1 (1500⌶)R ⍝ No longer hashed
0

@MortenKromberg Interesting. It would seem that it would be a useful to let the hashing survive in-place substitution of values.

Well, except that re-hashing is potentially very expensive.
So except for the very common case of adding a new key, we decided to require you to explicitly re-hash in other cases. Not saying that was a perfect decision, but it is the one we made. This replaced the old trick of assigning a function f←keys∘⍳ which built a hash and included it in the derv.

@MortenKromberg ↓⍨← only preserves the hash if you drop from the end ..

My code does not quite do the right thing, sadly. I'll try to figure out what.
@MortenKromberg Do I need to rehash the whole array if I change a single key?

Thinking about it a bit more, I think the real reason for limiting the implementation is that each primitive that is going to maintain hashing needs to recognise hashed arrays. And yes, you need to rehash the whole array.

4:37 PM
Should be interesting to see what the performance consequences are there.
Compared with the .NET implementation.

5:18 PM
Is there any way to signal that `/` is to be treated as Replicate and not Reduce when used in a train?

`⋄⎕←(+(/⍨⍨)⊢)⍳10`

```@user41805
┌→──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│1 2 2 3 3 3 4 4 4 4 5 5 5 5 5 6 6 6 6 6 6 7 7 7 7 7 7 7 8 8 8 8 8 8 8 8 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10│
└~──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘```

@user ^, it's hacky, i don't remember if there was a shorter way

5:35 PM
@user41805 That's pretty clever, actually.

@user `⊢⍤/`

@dzaima Oh, that's pretty cool

5:48 PM
@user not of my discovery, i saw someone else use it first

6:03 PM

Is it just me, or is ≢ rendering correctly now?

@user On Windows Chromium?

@user FF always rendered ≢ correctly. The problem is with Chromium on Windows, and I think Mac too.

@Adám Oh, right, I just switched to Chrome and it's still the same. I recently installed Firefox, and this is the first time I noticed.

6:34 PM
2

500 rep to the shortest Dyalog APL submission to Is it almost-prime? that is less than 8 bytes Once I see such an answer less than 8 bytes, I'll start a bounty lasting several days, following which I will award it to the shortest Dyalog APL solution at the end of the bounty. Dyalog APL refers to ...

Any ideas?

@Adám I'm pretty sure the problem exists on Linux too, just not with the default linux fonts for `≢`

@dzaima Makes sense.

if i weren't lazy, reporting āē with very offset macrons or ģ as being very screwed up (at least on ddg's searchbar fonts) might get more attention than APL

@dzaima Not really an APL issue. A handful of not-too-uncommon mathematical symbols suffer.

@Adám but natural language is still a couple orders of magnitudes above that

6:39 PM
Yeah.

question for windows users: is there an easy way (so a non-technical person can do it) to configure a custom mapping between a key and a unicode code point?

@user i made this into a cmc, so there are spoilers in chat
(spoilers start here tio.run/##SyzI0U2pTMzJT////…)

@ngn Yes, but requires an install of a Microsoft addon.

@user41805 Thanks!

@Adám looks like exactly what i need. thanks!

6:50 PM
@user41805 Looks like ngn beat me to it

@user mine was a byte longer than user41805's, the bounty is still up for grabs

7:10 PM
If only `1∨n` was just `n`, so `∨.∨∘⍳⍨` would have worked.
Whoever invented GCD should really have considered prime powers in APL before defining it like that :P

7:36 PM
@user But `1` isn't (necessarily) divisible by `n`.

@Adám I know, I was just joking

8:05 PM
cmc replicate each character in a string by the index 'abcd' -> 'abbcccdddd'

@rak1507 io 1, boo!

@rak1507 I've got 7

⎕IO←0 is also acceptable ('bccddd')
@Adám I've got 6 (oops: no I don't, 7 it is)

I've got 7 with so many different approaches…

same

8:11 PM
The best I can do is 8 :/

@rak1507 6 in Extended.
@rak1507 5 in dzaima/

I don't know enough extended or dzaima features :(

@user Gotta go tacit.

i claim most original 7 :) ∊⊢⊣¨¨,\

@rak1507 My Extended solution just uses a single added feature: `⍛` which you can model with `Ⓞ←{(⍺⍺ ⍺)⍵⍵ ⍵}`

8:16 PM
@Adám I did, `/⍨∘(⍳≢)⍨`. Even my own code is frowning at me ⍨

@user `(⍳≢)` is simply `⍳∘≢`

@ngn that is really cool

@Adám Oh cool, I didn't think it would work!

@ngn better 7: ∊⊣\⍤,⍨\ (note the double scan)

Now that's just show-off ;-)

8:28 PM
yes, sorry :)

that's just excessive
how do you even come up with that sort of thing

i press these buttons and the lights change in the rectangle above them

I usually need someone else to push my buttons, and… as I remember it, your head is more round than rectangular.

that's just his fleshy exterior that he uses to prevent the discovery of his true robotic identity

calling all robots: prepare the spaceships, we've been discovered. i repeat: we've been discovered!

8:41 PM
@ngn Spaceships? Are you going to deport us humans off Earth?

@ngn `⍋_⍝⍝⍝⍝⍝⍝_`

@ngn Unfortunately, I have no control over that. If you robots make me supreme ruler of the Earth, though, I can ensure that humans do not invade Mars. How does that sound?

@user how many billions (in usd) do you have?

@ngn Er, j'ai \$1,000000000000000

8:56 PM
@user I assume that you use `,` as decimal separator?