6 hours later…
8:17 PM
on APLcart there is "X⍳⍨∘⌽Y Position of last X in Y"
⎕←4⍳⍨∘⌽(1 2 3 4 2 3 4 3)

```@TessellatingHeckler
2```

which is the index from the end; is that intentional? Is there a common way to work with index-from-end? Is it expected to reverse Y then use the index?

@TessellatingHeckler Something like that, but it is a bit odd. It should probably give 7, no?

@Adám I was looking for 7, yes
⎕←{(8@(⊃⌽⍸4=⍵))⍵}(1 2 3 4 2 3 4 3)

```@TessellatingHeckler
1 2 3 4 2 3 8 3```

8:21 PM
@TessellatingHeckler You don't need to wrap the `@`-thing in a dfn.

that was my attempt, first of the reverse of the indexes, but I get the feeling that iota-underbar shouldn't be what I reach for first
@Adám the @ thing is SUPER FRUSTRATING

@TessellatingHeckler I wrote `4(⊢/∘⍸=)1 2 3 4 2 3 4 3`
@TessellatingHeckler How so?

@Adám the only answer I guess is that I don't understand it, but it's a case of everything I try throws an error until I salt and pepper it with parens everywhere

@Adám well to use `⍵` in the expression of a number `⍵⍵`, you do

⎕←{8@(⊃⌽⍸4=⍵) ⍵}(1 2 3 4 2 3 4 3)

8:26 PM
```@TessellatingHeckler
SYNTAX ERROR```

take the unnecessary looking outer parens off, syntax error
⎕←'*'@(2∘|) 1 2 3 4 5 ⍝ Boolean selection 1 0 1 0 1

@TessellatingHeckler You can put `⊢` instad of `)` and remove `(`

from the examples, no outer parens there, works fine

@TessellatingHeckler the result of `(⊃⌽⍸4=⍵)` is an array so you have `arr@arr arr`, which correctly is interpreted as `arr @ (arr arr)` just as `1@1 2` gives `1 2` as the right operand of `@`
@TessellatingHeckler there it's `arr @ fn arr`, and there fn can bind with `@` just fine

@dzaima and 2 jot modulo isn't an array .. does that mean a function can't be in an array?

8:29 PM
@TessellatingHeckler functions can't be in arrays, yes.

@Adám What is the difference between left and right "same"?

@TessellatingHeckler None.

@dzaima Only the monadic functions are called "same".

lol, ok

8:30 PM
(In Dyalog APL, this is so. Some dialect have monadic `⊣` mean `{}` or `{0 0⍴0}` or `{r←⍵}`.)

dyadically they are left and right similarly to min and max, that doesn't seem like it would be useful enough to be a thing, and yet you use them allllll the time

@TessellatingHeckler Dyadically, thay are basically to trains what `⍺` and `⍵` are to dfns.

@Adám oh so me not liking them being equal it is understandable. might think about replacing it in my APL

@dzaima Monadic `⊣` is very rare. Mostly used where it can be called monadically or dyadically.

⎕←(⊢/∘⍸=)

8:34 PM
```@TessellatingHeckler
┌┴┐
∘ =
┌┴─┐
⊢/ ⍸```

@Adám yeah, exactly what i thought, and I don't very much like that whole monadic & dyadic implemented the same thing

that's a bit mangled here

@TessellatingHeckler No.

@TessellatingHeckler I like the version here better.

8:36 PM

@dzaima Hm, I'm always slightly unhappy with the definition of `@`. It wasn't thought through properly.

without just hearing an explanation, is there a way I can break that down further to dig into it?

@Adám yeah, that's what you get for having only 2 proper array arguments, plus squeezing 2 different things in one

it looks like the bottom layer should resolve to "1 2 3 4 2 3 4 3 /⍸ 1 2 3 4 2 3 4 3" but that's silly

@TessellatingHeckler Does full parenthesising help? `(((⊢/)∘⍸)=)`

8:40 PM
@TessellatingHeckler the `⊢/` is joined together for a reason - it's a derived operator - right reduce

`⍞←8@{⌽<\⌽4=⍵}1 2 3 4 2 3 4 3`

`@Adám 1 2 3 4 2 3 8 3`

@dzaima Derived function, actually.

@dzaima right reduce? is that an idiomatic or efficient "last"?

@TessellatingHeckler both, probably. It just fits in a tacit expression better than `⊃⌽`

8:44 PM
@TessellatingHeckler Yes, but notice that `⊃⌽` and `⊢/` are different for higher-rank and/or nested arguments.

@Adám oh right. operator, derived? or is there some other descriptor for an operator that's got it's argument bound?
@Adám `⍢` is always fun

@dzaima Operand? `⊢/` is a derived function. `∘⊢` is a derived operator. `⊢∘⊢` is a derived function.
@dzaima Yeah, but why can't `8⍢(⊢/∩∘4)` work ⍨ (I know why.)

@Adám parenthesising didn't help while I was thinking of it doing a replicate instead of a reduce; but I get it now - a dyadic atop identifying the positions of the fours, interval index, then right-reduce that

8:59 PM
@TessellatingHeckler `⍸` there isn't "interval index" (the dyadic case), it's "where" - indexes of 1s

@dzaima no it isn't is it, derp. I wasn't actually thinking that it was doing the operation of looking up a position in a given array, but still slapped the wrong name on it
having the glyph have one name, the monadic operation another, the dyadic operation another, the casual understanding of "what it's doing" another term, another term if it's an operator .. I need to be more careful

@TessellatingHeckler Most documentation and guidance begins with the glyph and branches to each meaning. The idea of APLcart is to begin with the meaning and show the glyph.

at first i wanted to say that there are no glyphs that are both an operator and a function, but then i remembered about the slashes. those damn annoying things ಠ_ಠ

@dzaima Darn schizos.

⎕←','@(' '∘(⊢/∘⍸=)s)⊢s←'This is a sentence with a 6'

9:06 PM
```@TessellatingHeckler
This is a sentence with a,6```

so hurray that works; is it possible to combine it without the temporary variable?
"works" meaning "replaces the last space with a comma"

@TessellatingHeckler Only if you make it a dfn, but what's wrong with:
`⍞←','@{⌽<\⌽' '=⍵}'This is a sentence with a 6'`

`@Adám This is a sentence with a,6`

↑ note that `f\` with `f` being a builtin is pretty much always just a pure magic idiom
aplcart explains it though
@Adám pls escape `\` to `%5C` in url

?_?
⎕←{(','@(⊃⌽⍸⍵=' '))⍵} 'This is a sentence with a 6'

9:11 PM
```@TessellatingHeckler
This is a sentence with a,6```

`⍞←{','@(⊃⌽⍸⍵=' ')⊢⍵} 'This is a sentence with a 6'`

`@Adám This is a sentence with a,6`

@TessellatingHeckler If you put four or more spaces on the left of your `⎕←` or `⍞←` it will look better.
@TessellatingHeckler You want an explanation?
@dzaima Doesn't your browser do that for you?

`⎕←<\1 2 3 4 5`

```@TessellatingHeckler
1 1 0 0 0```

9:20 PM
@TessellatingHeckler You know how scan works?

they are all less than each other, and less-than doesn't roll up in the same way addition does, how is this not `1 1 1 1 1`

@Adám it doesn't seem to (chromium 74.0.3729.169)

@Adám no, although I have met it before
result of the last application on the left, each item of the array on the right, I think

@dzaima Hm, mine displays normal chars, but copying gets me the URI-encoded version.

which makes sense for
⎕← +\1 2 3 4 5

9:21 PM
```@TessellatingHeckler
1 3 6 10 15```

@TessellatingHeckler Consider the `<` truth table:
`⎕←('<'∘,,⊢⍪∘.<⍨)0 1`

```@Adám
< 0 1
0 0 1
1 0 0```

but `(0 < 1) ((0 < 1) < 2) (((0 < 1) < 2) < 3)`

@TessellatingHeckler The first element is copied in as-is.

oops, ok

9:24 PM
@Adám it does display as `<\`, but copying only escapes the `<`. it copies exactly what's passed to `setUrl`, and, to add to that, `setUrl("%3C%5C")` shows `<%5C` in the URL..

1 copies as is.
1 < 2 is true so the second element is 1
the result of previous application was 1 so 1<3? true so it's 1
the result of previous application was 1 so 1<4? true so it's 1
the result of previous application was 1 so 1<5? true so it's 1
so clearly I don't understand scan because that's not what it does

@TessellatingHeckler no, it's `0 (0 < 1) (0 < 1 < 2) (0 < 1 < 2 < 3)`

@dzaima You type faster than me.

@dzaima where does the 0 come from in `<\ 1 2 3 4 5` if the first element is copied as-is ?

@TessellatingHeckler oh whoops, i didn't look at what exactly you posted, that's an example for `<\0 1 2 3`

9:29 PM
and even then `(0 < 1 < 2)` still looks like it should be 1
(I was guessing that 0 came from a prototype number)

`⎕←<\0 1 2 3 ⊣ 'it is'`

```@dzaima
0 1 1 0```

`⎕←0 (0 < 1) (0 < 1 < 2)  (0 < 1 < 2 < 3) ⊣ 'same as above'`

```@dzaima
0 1 1 0```

ah
hey chat why do you deduplicate my comment
double "ah" was intentional as an emotional indicator

9:32 PM
@TessellatingHeckler F5, it does that

it's because APL reduces right to left
`⎕←<\1 2 3 4 5`

```@TessellatingHeckler
1 1 0 0 0```

@TessellatingHeckler Exactly.

1 copies as is
1 < 2 is 1
(1 < 2 < 3) becomes 2 < 3 is 1 then 1 < 1 is 0

you can think of `\` as `{⍺⍺/¨ prefixes ⍵}`

9:33 PM
@TessellatingHeckler Right, and with that in place, now look at the truth table.

@Adám uhh, look for what in the truth table? that only a 0 < 1 can result in true, so as soon as there's a 1 on the left of < the rest of the scan will always be 0 ?

@TessellatingHeckler Yes!
It doesn't matter what comes to the right of that 1, since there is a 1 on the left, everything beyond it is cancelled.

@Adám soooo how does @ with a function bound to the right, as linked in your example, work?
does it not use the function once on each element of the array?

@dzaima Better now?

@dzaima I don't know that doing so would help :D

9:43 PM
@TessellatingHeckler No, it uses the function once on the entire array, and the result must be a mask for the array. That mask is then ravelled and used to filter the ravelled array, and the left operand is applied to that list.

```⋄ f←{⎕←'f sees:',⍵ ⋄ ⎕←'f returns:',r←10×⍵ ⋄ r}
⋄ g←{⎕←'g sees:',⍵ ⋄ ⎕←'g returns:',r←2|⍵ ⋄ r}
⋄ ⎕←f@g 1 2 3 4 5```

```@Adám
g sees: 1 2 3 4 5
g returns: 1 0 1 0 1
f sees: 1 3 5
f returns: 10 30 50
10 2 30 4 50```

@TessellatingHeckler Does ^ help?

@Adám well neat; I should have picked that up from the example `'*'@(2∘|) 1 2 3 4 5` because of course modulo works on an array

9:49 PM
@Adám I wish I had a middleman between a function call and the specific code called, would be nice to have an `)explain` that does that kind of thing in my apl

@dzaima Just make an operator for it!

@Adám adding that everywhere in every expression for every function everywhere every time i want to explain a thing is a bit of a hassle
also that couldn't add explanations for operators themselves

thanks :)
how do `{','@(⊃⌽⍸' '=⍵)⊢⍵} text` and `','@{⌽<\⌽' '=⍵} text` compare - apart from the dfn bit - is two reverses and a scan costlier?`
my guess is that it's not obvious; surely "reverse" doesn't actually do an in-memory reverse, in any situation where it can be optimised not to(?).

@TessellatingHeckler tio.run/##S07MK0ss/…
hmm, getting mixed results here

10:01 PM
@Adám hmm; now I guess `<\` could be special cased more easily than `⊃⌽⍸` could be
well, they're at least similar. Neither is 100x worse

@TessellatingHeckler Both versions are likely to be dramatically sped up in the next few years, and I expect them eventually to have the same performance.

oh heyy, is that standard Markdown

@TessellatingHeckler Nah, if we introduce "thunks" they should be the same. `⊃⌽⍸` would only look for the index of the first from the end, and `⌽<\⌽` would know to begin from the end and mask out all but the first hit 1.
@TessellatingHeckler There is no such thing.
@TessellatingHeckler I can't wait for thunks. They will make a huge difference. `⊃⌽⍸⍵` is on line 11 and `⌽<\⌽` is on line 6 in the list of expressions to be dramatically sped up:

10:17 PM
@Adám I think I've seen "thunk" from Haskell-land as an unevaluated delayed-execution block. What is it in APL and how will it help performance?

@TessellatingHeckler pretty much the same

@TessellatingHeckler That is indeed it. Currently `3↑2×HugeArray` does way to much multiplication. If that is held off until after the `3↑` we have potentially infinite speedup.
Similarly, `⊢/⍸` should just start looking for a 2 from the right, and return its index, rather than finding all the indices of ones, then taking the last one.
And even more so with `⊢/⍸a=b` which doesn't even need to to do all those comparisons, just compare from right to left until we find a match, then return its index.

imo another good example could possibly be `1,2,arr` vs `(1,2),arr` (though that's only a 2x speedup and doesn't generalize to different ranks, but those could be improved too)

@dzaima It is on line 13, about in the middle.

10:25 PM
If that's not already happening, Dyalog must be a sea of individual special-cases inside 👀

@TessellatingHeckler Yup. See this.

i'm just more afraid of how much will it hurt the performance of tiny, often called functions where vectorizability is impossible

@dzaima Did you see that talk?

@Adám IIRC it said something about having a check for if the arguments are large, but that check would be a constant performance penalty

@dzaima Yeah. We'll see. Marshall is a very clever guy.

10:33 PM
I'll watch it
Marshall's talk on sub-nanosecond searches killed me

i'm also curious how much time does the current idiom checking take, but at least it can probably sometimes be done statically with a Sufficiently Smart Compiler

@dzaima The idiom system works at tokenising time, so there's no overhead at runtime.

10:46 PM

@dzaima Yes, that's the downside of tokeniser idioms, and why we ultimately need thunks.

@Adám what part of that shows a downside of tokenizer idioms? the results are pretty much the same, with the dfn overhead for dfns