🦋 Welcome to the IRC channel of the core developers of the Raku Programming Language (raku.org #rakulang). This channel is logged for the purpose of history keeping about its development | evalbot usage: 'm: say 3;' or /msg camelia m: ... | Logs available at irclogs.raku.org/raku-dev/live.html | For MoarVM see #moarvm
Set by lizmat on 8 June 2022.
00:00 reportable6 left 00:02 reportable6 joined
Geth rakudo: vrurg++ created pull request #5314:
Implement methods `andthen` and `orelse` on Promise
01:59
roast: vrurg++ created pull request #836:
Add tests for Promise new `andthen` and `orelse` methods
02:00
02:21 squashable6 left 02:24 squashable6 joined 03:24 evalable6 left, linkable6 left 03:26 linkable6 joined, evalable6 joined 05:42 evalable6 left, quotable6 left, reportable6 left, linkable6 left, shareable6 left, coverable6 left, greppable6 left, bisectable6 left, squashable6 left, benchable6 left, tellable6 left, bloatable6 left, nativecallable6 left, sourceable6 left, statisfiable6 left, releasable6 left, unicodable6 left, notable6 left, committable6 left, benchable6 joined, releasable6 joined, committable6 joined, greppable6 joined, statisfiable6 joined 05:43 tellable6 joined, bloatable6 joined, coverable6 joined, notable6 joined, unicodable6 joined 05:44 squashable6 joined, sourceable6 joined, linkable6 joined, shareable6 joined, reportable6 joined, bisectable6 joined, quotable6 joined 05:45 nativecallable6 joined, evalable6 joined 06:00 reportable6 left, reportable6 joined 07:12 committable6 left, tellable6 left, greppable6 left, notable6 left, unicodable6 left, statisfiable6 left, evalable6 left, releasable6 left, reportable6 left, nativecallable6 left, quotable6 left, bloatable6 left, linkable6 left, benchable6 left, bisectable6 left, shareable6 left, coverable6 left, sourceable6 left, squashable6 left, greppable6 joined 07:13 shareable6 joined, squashable6 joined, unicodable6 joined, nativecallable6 joined, statisfiable6 joined, evalable6 joined, sourceable6 joined, bloatable6 joined, coverable6 joined, linkable6 joined 07:14 notable6 joined, quotable6 joined, reportable6 joined, bisectable6 joined, tellable6 joined 07:15 benchable6 joined, releasable6 joined, committable6 joined 08:29 sena_kun joined
[Tux] Rakudo v2023.06-98-g34a1a5da5 (v6.d) on MoarVM 2023.06-1-g63af27399
csv-ip5xs0.836 - 0.915
csv-ip5xs-205.190 - 5.403
csv-parser3.714 - 3.793
csv-test-xs-200.395 - 0.512
test6.739 - 7.559
test-t1.400 - 1.401
test-t --race0.858 - 0.867
test-t-2020.799 - 20.937
test-t-20 --race6.246 - 6.784
08:36
08:47 ab5tract joined
ab5tract I've found a nightmare of a bug in the REPL: gist.github.com/ab5tract/bb094655f...d83e54264f 08:58
tested on linux/x64 and macos/arm64, present in 2023.06 and at least as far back as 2022.12 09:00
this is the kind of heartbreaker bug that makes me hesitate about loving and using this language as much as I do :/ 09:01
tl;dr -- @foo.map: ( ... } only iterates 102 times in the REPL if it is the last statement on an input line 09:14
lizmat ab5tract: and what is the error ? 09:21
if it doesn't get reported, it doesn't get fixed 09:22
ab5tract @foo is 103 elemets
it only iterates 102 of them
lizmat Ah. I think I see wht 09:24
*why
it's because .gist will limit the number of iterations
@foo.map({...}).sink 09:25
if you're doing just @foo.map() 09:26
ab5tract the behavior isn't replicated by `do for @foo`
lizmat: that's unacceptable
lizmat what is unacceptable?
ab5tract having to call .sink
(imo, of course) 09:27
lizmat in your example, it's the output generation of the result (a .Seq) that causes the map to run
tryt doing: 09:28
ab5tract a user should never have to know about some limit of gist, or of sinking their map calls.
lizmat say "foo"; @foo.map({ .print }
and you'll see that nothing happens apart for the "foo"
ab5tract @foo.map: { say $++ }
lizmat that's because the REPL in that case sees that STDOUT has changed and assumes that that's what you wanted
nemokosch is this even REPL specific? 09:29
lizmat this is VERY REPL specific
@foo.map: { say $++ }
does *not* create any output *until* it starts running the map
nemokosch I mean a Seq can always be lazy 09:30
lizmat and it is
that's why
nemokosch then I don't see the problem, honestly
lizmat say "foo"; @foo.map({ .print }
will only say "foo" and nothing else
because that caused output *BEFORE* the Seq is returned
ab5tract: do you understand what I'm trying to say? 09:31
ab5tract not exactly, no. because if I remove that `say`, then I get 102 iterations of @foo.map: { .print } 09:32
nemokosch mutating shared state with lazy "loops" is next to eval... I mean evil 😄
lizmat ab5tract: what do you think a [email@hidden.address] returns? 09:33
ab5tract: what do you think a "@foo.map(...)" returns?
ab5tract it returns a Seq, if I'm not mistaken
lizmat indeed...
m: my $a := (^10).map({ .say }) 09:34
camelia ( no output )
lizmat see how that doesn't generate any output ?
ab5tract m: (do for ^10).WHAT.say
camelia ===SORRY!=== Error while compiling <tmp>
Missing block
at <tmp>:1
------> (do for ^10⏏).WHAT.say
expecting any of:
block or pointy block
ab5tract m: (do for ^10 { $_ }).WHAT.say
camelia (List)
ab5tract so that explains the distinction 09:35
lizmat indeed
ab5tract I still think this is a really awkward corner of things
lizmat m: my $a := (^10).map({ .say }); say $a.gist
camelia 0
1
2
3
4
5
6
7
8
9
(True True True True True True True True True True)
lizmat note that the generation of the .gist now causes the .map to run
nemokosch the True's are the return value of say, for the record
lizmat yup
nemokosch and iirc gist itself would hit an upper limit of how many values it is willing to fetch 09:36
lizmat and .gist is limited to showing 100 entries... to figure out there are more, apparently it runs to 102
nemokosch after all, it's just a "readable representation"
lizmat right
ab5tract: try running the repl with RAKU_REPL_OUTPUT_METHOD=Str set 09:38
nemokosch this is no easy topic because it can make a difference if the underlying iterator itself is marked "lazy", in which case a gist won't fetch a single value
but at the end of the day, mutating a shared variable in a map call is probably something you should stay away from 09:39
ab5tract lizmat: I don't see a change 09:40
nemokosch: that's not written in stone anywhere. It's a rule I happen to live by in codebases
repls are different beasts
and even then, it should be a cosmetic choice to stick to "no side effects in maps" 09:41
nemokosch but fundamentally, as you can see, the REPL does no magic here, so the bad idea doesn't magically turn into a good idea
ab5tract The REPL is doing magic here. This bug doesn't affect regular code 09:42
nemokosch all it does is to call "say" or something akin 09:43
lizmat say $value."$method"()
to be precise, with $method being set to "gist" by default
see also: github.com/Raku/problem-solving/issues/194 09:45
and: github.com/rakudo/rakudo/commit/28...f0cb8a3d67 09:46
ab5tract switching to Str didn't change the behavior 09:47
nor to raku
anyway, I guess this is considered not a bug but I find it both surprising and LTA 09:48
nemokosch well, whether you like it or not - do you recognize that it is consistent? 09:50
btw the one with .raku should have "worked" probably, as that fetches all the elements 09:51
ab5tract damnit 09:52
off by one :)
yeah, it works
Str as well 09:53
now, neither of those are really options for the use case this surfaced in ... which was analyzing 700_000 events
nemokosch it's borderline questionable why you use the "read eval print loop" if what you get back is not worth printing 😛 09:55
ab5tract I'll just have to remember to sink any map calls like that in the future, or just stick to for
nemokosch but then there was the sink way 09:56
or I suppose the eager way as well
eager @a.map: { $x++ };
ab5tract regarding why use a REPL for analyzing such a large number of events, it costs a lot of time to load those events in Raku 09:58
good point on the eager.. lots of ways out of the issue
lizmat: tangential but related (because same outage), was it a conscious choice to avoid bagging alike hashes in a BagHash? 10:00
It's similar situation as above, where DWIM is in the eye of the beholder but...
lizmat ab5tract: why would you use the REPL to check 700K events ?
oops... ok 10:01
ab5tract: hashes are not value types, you can only bag value types in a sensible way
ab5tract fair enough 10:02
lizmat and neither are maps, sadly:
m: dd ().Map.WHICH
camelia ObjAt.new("Map|3555763753664")
ab5tract how do object hashes work again?
lizmat the same as QuantHashes: they use the .WHICH as the key 10:03
ab5tract it makes sense, but its a shame
lizmat are the values in the hash numeric ? 10:04
ab5tract because I can't think of an easy way to check for duplicate events in that haystack of events
lizmat ab5tract: also, I don't understand the "it costs a lot of time to load those events in Raku" comment 10:05
ab5tract nope, just plain old un-schema'd hashes that happen to generally follow each other
nemokosch for Maps not being a value type: the values can be containers, just like with List 10:06
ab5tract lizmat: you don't see the difference between loading 700k events into memory once to then run analysis on, versus loading them each run
?
nemokosch and just like with Pair, actually, which is kind of important but I guess y'all already know that
ab5tract we are talking 5+ minutes on a from-json call 10:07
lizmat ab5tract: ah, I see
perhaps you could do:
ab5tract not even sure how much faster it would be if the output was .raku and I eval'd it
lizmat @foo.map(*.raku).Bag ?
.raku on hashes *does* sort the keys, so should be reproducible 10:08
ab5tract lizmat: yeah, I thought about that, but I don't think .raku has any guarantees for key order in the output (as it shouldn't)
whereas %a ~~ %b does seem to do the full-depth comparison 10:09
lizmat .raku *does* sort keys
ab5tract oh! TIL
lizmat reason: it's often used as a debug tool, and then it makes a lot of sense :-) 10:10
ab5tract: also, do you have control of the JSON generation?
if so, then maybe raku.land/zef:lizmat/JSON::Fast::Hyper might be something for you 10:11
ab5tract that's interesting indeed 10:13
unfortunately not in this case
lizmat well, you could run it through a from-json -> to-json sequence once
and have faster loadable JSON afterwards 10:14
assuming the top level is a positional, which from your questions, I assumed
ab5tract yeah, that's the case.
now I'm curious about what a bare EVAL against a .raku of that top level positional would be like 10:15
in terms of time
lizmat I doubt it's going to be a big difference 10:16
and probably slower I'd thnk
ab5tract well that's kind of a bummer. especially since we have deprecated to-json and from-json in core (I'd prefer to see heavily optimized core versions of those) 10:21
lizmat ab5tract: also, docs.raku.org/routine/repl might be of interest for you
ab5tract thanks for that! I *thought* there was something like that available, but I thought it was in the ecosystem 10:22
nemokosch I don't know why it was pushed out of core but JSON::Fast has an implementation that really looks like that 10:24
lizmat yeah, technically, they're mostly identical 10:26
ab5tract any recollections why we decided to deprecate? because having excellent json wrangling skills today might be akin to having excellent text wrangling skills back in the day 10:29
s/skills/capabilities/g
lizmat I think the main reason was to be able to get a better JSON parser without needing to update / upgrade Rakudo 10:32
FWIW, I wouldn't be against making JSON::Fast part of the core
and I don't think I ever was...
ab5tract :) 10:33
it seems to me that the way things work right now demonstrate that you can both have core implementations as well as swappable parsers to replace those implementations 10:34
so maybe that concern could be considered alleviated at this point 10:35
but maybe I'm missing something.. wouldn't be the first time ;) 10:37
11:59 squashable6 left 12:00 reportable6 left 12:02 squashable6 joined, reportable6 joined 12:31 squashable6 left 12:33 squashable6 joined 13:29 ab5tract left 15:20 jgaz left 16:13 ab5tract joined 16:33 ab5tract left 16:46 jgaz joined 18:00 reportable6 left 18:01 reportable6 joined
gfldex Was alias infix:<≅> for infix:<=~=> omitted intentionally? 19:09
lizmat m: say 4 ≅ 4 19:36
camelia True
lizmat it wasn't ?
gfldex: ^^
afk&
m: say 4 ≅ 4.000000000000001 19:38
camelia True
lizmat really afk&
gfldex ENODOC then 19:41
m: my $a ≔ 42;
camelia ===SORRY!=== Error while compiling <tmp>
Confused
at <tmp>:1
------> my $a⏏ ≔ 42;
expecting any of:
infix
infix stopper
statement end
statement modifier
statement modifier …
gfldex How about that one?
20:34 sena_kun left 21:48 nativecallable6 left, bisectable6 left, quotable6 left, tellable6 left, notable6 left, statisfiable6 left, bloatable6 left, evalable6 left, benchable6 left, committable6 left, shareable6 left, releasable6 left, unicodable6 left, sourceable6 left, squashable6 left, coverable6 left, reportable6 left, greppable6 left, linkable6 left, benchable6 joined 21:49 tellable6 joined, linkable6 joined, squashable6 joined, nativecallable6 joined, reportable6 joined, statisfiable6 joined, unicodable6 joined, coverable6 joined, quotable6 joined, releasable6 joined, notable6 joined 21:50 committable6 joined, bisectable6 joined 21:51 sourceable6 joined, greppable6 joined, evalable6 joined, bloatable6 joined, shareable6 joined 22:51 reportable6 left, nativecallable6 left, committable6 left, benchable6 left, greppable6 left, squashable6 left, notable6 left, coverable6 left, shareable6 left, bisectable6 left, quotable6 left, statisfiable6 left, linkable6 left, bloatable6 left, evalable6 left, unicodable6 left, sourceable6 left, tellable6 left, releasable6 left, benchable6 joined, reportable6 joined 22:52 squashable6 joined, evalable6 joined, quotable6 joined, notable6 joined 22:53 bisectable6 joined, coverable6 joined, releasable6 joined, greppable6 joined, nativecallable6 joined 22:54 unicodable6 joined, committable6 joined, tellable6 joined, statisfiable6 joined, linkable6 joined, sourceable6 joined, bloatable6 joined, shareable6 joined