🦋 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: ... | log inspection situation still under development | For MoarVM see #moarvm
Set by lizmat on 22 May 2021.
00:00 evalable6 joined, linkable6 joined, releasable6 joined 00:02 reportable6 left 00:05 reportable6 joined 02:25 Xliff left 06:02 reportable6 left, reportable6 joined 07:25 Altai-man_ joined 07:28 Altai-man_ left 08:52 |Tux| joined
lizmat vrurg: how would that make a difference ? 09:39
09:48 gfldex left 09:58 djinni` left 10:06 djinni` joined 10:13 Altai-man left 10:24 sena_kun joined
lizmat m: use Test; is-deeply (1|2,3), (1|2,3) 10:47
camelia ok 1 -
11:24 linkable6 left, evalable6 left, evalable6 joined 11:26 linkable6 joined 12:02 reportable6 left 12:03 reportable6 joined 12:43 cognominal left
Geth rakudo/rakuast: 05340cbd42 | (Jonathan Worthington)++ | 14 files
Prepare for expression thunking

Various contexts imply a thunk on an expression. Functionality that needs this includes:
  * Attribute default values
  * The LHS of `xx` (and other such thunky operators)
... (11 more lines)
13:22 morayj joined
vrurg lizmat: I only meant that the error is totally correct and there is no reason for confusion. Assignment creates a container – thus the error. In the first example it just takes the default from $!descriptor. Technically it only means that we can't have a valid .raku representations for a sparse array. 13:31
*representation 13:32
lizmat I understand the technicality
m: my Int:D @a = 1,2,3; dd @a[1]:delete; dd @ 13:33
camelia Int @a = 2
Array @ = []
lizmat m: my Int:D @a = 1,2,3; dd @a[1]:delete; dd @a
camelia Int @a = 2
Array[Int:D] @a = Array[Int:D].new(1, Int:D, 3)
lizmat still, there are ways to create holes in these arrays
which leads me to think that assigning Nil to these arrays should *not* be an error 13:34
but instead, treated like a :delete here, just exposing the type object
vrurg I would disagree. It's a way to allow for errors in user code. 13:35
lizmat m: my Int:D @a = 1,2,3; dd @a[1]:delete; dd @a; @a[1] = "foo"
camelia Int @a = 2
Array[Int:D] @a = Array[Int:D].new(1, Int:D, 3)
Type check failed in assignment to @a; expected Int:D but got Str ("foo")
in block <unit> at <tmp> line 1
lizmat while still having the typecheck on any other value
vrurg With :delete one is explicit about their intentions.
lizmat with = Nil as well
m: my Int:D @a = 1,2,3; dd @a[1] = Nil 13:36
camelia Type check failed in assignment to @a; expected Int:D but got Int (Int) (perhaps Nil was assigned to a :D which had no default?)
in block <unit> at <tmp> line 1
vrurg Not if Nil is returned from another routine.
Especially if the rouinte is from a 3rd-party code.
lizmat so in order to be able to get a valid .raku for sparse arrays, we should introduce yet another value that indicates absence of a value ? 13:37
and what would prevent subroutines from returning *that* special value ? 13:38
vrurg I think there must be no way to create a hole by assigning a single value. Only with a list where the whole array is changed.
lizmat m: my @a = Nil # is this a List ? 13:39
camelia ( no output )
lizmat m: my @a = Nil,
camelia ( no output )
vrurg If I stress out the part about the whole array – both are almost valid. Except that I wouldn't treat Nil in this context as special anyway. 13:41
Nil has clear meaning. Let it remain this way. 13:42
lizmat so what *is* the meaning of Nil then, according to you?
vrurg It resets to the default value.
lizmat right, and in the case of my Int:D @a, the default value is Int:D 13:43
it does *not* say anything about typechecking 13:44
"When assigned to a container, the Nil value (but not any subclass of Nil) will attempt to revert the container to its default value; if no such default is declared, Raku assumes Any."
is what docs.raku.org/type/Nil#index-entry...assignment says
vrurg m: my Int:D $a = 1; $a = Nil; 13:45
camelia Type check failed in assignment to $a; expected Int:D but got Int (Int) (perhaps Nil was assigned to a :D which had no default?)
in block <unit> at <tmp> line 1
lizmat yes, I know the current behaviour :-)
bisectable6: my Int:D $a = 1; $a = Nil;
bisectable6 lizmat, Will bisect the whole range automagically because no endpoints were provided, hang tight
lizmat, Output on all releases: gist.github.com/e45b7066bd41a0dcb5...cea8b02f93 13:46
lizmat, Bisecting by output (old=2018.10 new=2018.11) because on both starting points the exit code is 1
lizmat, bisect log: gist.github.com/18c70e429703075727...5ece37dd86
lizmat, (2018-10-27) github.com/rakudo/rakudo/commit/46...96034408c8
lizmat, Bisecting by exit code (old=2016.07.1 new=2016.08.1). Old exit code: 0
lizmat, bisect log: gist.github.com/fe938df236db3cf0b5...bbd2c75b2c
lizmat, (2016-07-22) github.com/rakudo/rakudo/commit/4e...e207f55da9
lizmat, ⚠ New output detected, please review the results manually
lizmat, Output on all releases and bisected commits: gist.github.com/62c2db4814b350af0d...9f52f9e1e9
lizmat anyways, feels like I've spent the past 4 days on a wild goose chase 13:47
if we indeed make my Int:D @a = 1,2,Nil,4 a typecheck error 13:48
vrurg I'm just pointing at it because I want things to be consistent. Assignment to an array element creates a Scalar. From this point on we must follow the rules about scalars.
lizmat there is indeed no way to create a .raku representation of sparse arrays using Nil
and we would need to be thinking on how we're going to represent them in other ways
assignment doesn't create a scalar 13:49
you can assign to an element in an array that happens to be bound to a scalar
vrurg That why I'd rather have class Hole here. @a = Hole, Hole, 1; @a = 1, 2, Hole.new(:10count), 3; etc.
lizmat m: my @a = 1,2,3; @a[1] := 42; @a[1] = 666
camelia Cannot assign to an immutable value
in block <unit> at <tmp> line 1
vrurg That's binding, not assignment. 13:50
lizmat the second is assignment
which no longer works, because I nuked the scalar container with the := 42 13:51
vrurg But there is a value in the element already. It's not nqp::null
lizmat you said: "Assignment to an array element creates a Scalar" that is incorrect
vrurg I.e. there is no whole at this position – thus no need to feel it. I mean, a Scalar is created only when a hole if filled.
I just skipped the part about the hole for simplicity.
s/there no whole/there is no hole/ 13:52
I'm typing too fast. s/feel/fill/
lizmat well, actually, it's slightly more complicated than than 13:53
an AT-POS on a hole returns a Scalar container that will be bound to the element in the array *only* upon assignment
vrurg I might be missing something, apparently, but when I look at ASSIGN-POS I don't see it calling AT-POS but it works on $!reified directly and it creates a Scalar from $!descriptor manually. 13:56
lizmat ASSIGN-POS makes it clear that you want to assign, so it doesn't need the extra magic 13:57
it only is conceptually AT-POS(i) = value
m: my @a; say @a.AT-POS(2_ 13:58
camelia 5===SORRY!5=== Error while compiling <tmp>
Unable to parse expression in argument list; couldn't find final ')' (corresponding starter was at line 1)
at <tmp>:1
------> 3my @a; say @a.AT-POS(27⏏5_
expecting any of:
lizmat m: my @a; say @a.AT-POS(2)
camelia (Any)
lizmat m: my @a; my $b := @a.AT-POS(2); dd @a
camelia Array @a = []
vrurg m: my @a; say @a.AT-POS(2).VAR.^name
camelia Scalar
lizmat m: my @a; my $b := @a.AT-POS(2); dd @a; $b = 42; dd @a
camelia Array @a = []
Array @a = [Any, Any, 42]
13:59 AlexDaniel left
lizmat note that elem 2 doesn't exist in the array until you actually assign 13:59
vrurg Anyway, I see no good in creating a hole by assigning a single element. This is error-prone and :delete should be sufficient here. 14:00
Lists are different.
14:01 AlexDaniel joined
vrurg For lists we already treat one type differently. So, no problem to get another one. It would make it possible to @a.raku to create a valid representation. 14:01
m: my @a = Slip.new(1,2); say @a.raku 14:02
camelia [1, 2]
vrurg With Hole it would also spare us a number of extra allocations in cases like @a = 1, 2, Hole.new(1000000), 3 14:04
The only problem for me with this approach is that I don't see a syntax as good as is |(...) for Slip. 14:05
lizmat Hole xx 1000000 feels more appropriate fwiw
vrurg lizmat: Whatever. But xx will eventually create a List with $!reified allocated. Hole.new is a single compact object. 14:07
Though we can get special handling for it with xx. 14:08
lizmat yeah, just adding a Hole:U candidate that returns a Slip 14:09
vrurg As to the syntax, I played on my side with operators :* and :^ for Hole.new(:count) and Hole.new(:until). Both are available. So, something like: 1, 2, :*100, 3 - would be able to create a sparse List.
lizmat so do we have a problem solving issue for this 14:10
vrurg No need to return a Slip if Hole is treated by &infix:<,>
lizmat: No, I just played with the idea in the original issue. But somehow I didn't consider problem-solving for it. 14:11
lizmat I guess it's time now for a ps issue :-)
vrurg Will try to make one later today.
Ok, I should do at least something for my $job now... :) 14:12
nine I think the sparse array discussion could benefit from an extensive look at actual real world use cases 14:19
vrurg nine: there is a few in github.com/Raku/problem-solving/issues/279 14:21
nine vrurg: I don't see anything about how and why real world programs would use this 14:33
vrurg Science calculations may benefit from it, in particular. Sparse data structures are quite common in there. 14:34
I've seen a couple of mentions of sparse arrays before too. 14:36
Plus, we do have a situation where @a.raku cannot be reverted back into the data structure simply because there is no way to express holes.
nine That's what I guessed. But I don't know what such structures will actually look like. Is it common to have one hole? Multiple? Are theses holes just a few slots or are we talking about 10000s? Is this only about one dimentional arrays? I think sparse matrices are quite common as well 14:38
vrurg Basically, when a matrix is created it is expressed in terms of lines. So, having a linear hole should be fine. 14:44
Otherwise it'd be better to discuss in a problem-solving when I open it. 14:45
15:01 b2gills left 15:19 cognominal joined 15:27 b2gills joined
vrurg lizmat: actually, there is no need for a new problem-solving, github.com/Raku/problem-solving/issues/279 is there already. 15:32
Geth rakudo/rakuast: 0d51fa56d1 | (Jonathan Worthington)++ | 2 files
Don't visit undefiend children
rakudo/rakuast: 8a931d1b6b | (Jonathan Worthington)++ | 8 files
Implement default arguments in RakuAST

This is the first consumer of the expresison thunking support: since we need to install the default value producer into the Signature object for non-trivial cases, we need to thunk it. Much of the infrastructure for building that thunk is factored out, so hopefully dealing with further such situations will be relatively straightforward (some more than others).
|Tux| Rakudo v2021.05-16-g750c5d04a (v6.d) on MoarVM 2021.05-14-g0a62f0c6a
csv-ip5xs0.875 - 0.890
csv-ip5xs-208.572 - 8.892
csv-parser25.578 - 25.847
csv-test-xs-200.368 - 0.378
test7.721 - 7.777
test-t1.972 - 2.031
test-t --race0.875 - 0.900
test-t-2034.109 - 34.511
test-t-20 --race9.955 - 11.427
16:22 morayj left
lizmat notable6: weekly 16:51
notable6 lizmat, 3 notes: 2021-06-09T12:12:57Z <lizmat>: www.youtube.com/yapcna ; 2021-06-10T09:05:57Z <lizmat>: p6steve.wordpress.com/2021/06/09/c...lace-html/ ; 2021-06-14T12:46:10Z <lizmat>: propuestas.eslib.re/2021/salas/raku-and-friends
17:07 gfldex joined
lizmat notable6: weekly reset 17:19
notable6 lizmat, Moved existing notes to “weekly_2021-06-14T17:19:49Z”
tonyo nine: it looks like clang sets the rest of the register to 1 if the incoming type doesn't match, eg coercing a 32b type to 8b 0xFE -> 0xFFFFFFFE, that's why that make test fails and assigning to `int` makes that test work 17:57
*coercing a signed 32b
18:02 reportable6 left 18:04 reportable6 joined
lizmat and another Rakudo Weekly News hits the Net: rakudoweekly.blog/2021/06/14/2021-24-missing/ 18:05
nine tonyo: "The caller of a function is responsible for signing or zero-extending any argument with fewer than 32 bits. The standard ABI expects the callee to sign or zero-extend those arguments." developer.apple.com/documentation/...-platforms 18:23
And that clearly means that NativeCall is doing it wrong and the test and clang are right. Which incidentally follows from nine's first lemma of debugging: the bug is always in your own code. 18:25
ugexe unless its my code
tonyo if you pass something that doesn't fill the type, it works fine. passing 0xE gives the correct value 18:31
passing 0x1E also gives me the correct value 18:32
i was digging around in nc for a long time before i figured out i should look at what's actually happening on the assembly side 18:33
that doc applies to the caller ensuring 8b numbers are signed correctly. this isn't an issue of the sign not being right but the register being F padded rather than 0 padded for the other 24b 18:37
0xFFFF_FFFE isn't a signing problem of 0xFE, the complement doesn't match 18:40
MasterDuke while people are here and on a sort-of related topic, can in interest anyone in my gmp-on-msvc problem? turns out it's not just nativecall, but somewhere ints/longs/whatever aren't being handled correctly 18:41
github.com/MoarVM/MoarVM/pull/1402...cea8089127 has the current state of my changes for windows, but it's still getting the errors
tonyo masterduke send the objdump -dt of the built test that you were commenting on 18:42
MasterDuke m: my int $int_min = -9223372036854775808; say ($int_min +> 16 == -140737488355328); # this is saying False
camelia True
MasterDuke and the calculated value is instead -18446603336221196288 18:43
i can send the output of the failing nativecall dll that's generated, but it's pretty big 18:45
it's 10m 18:46
heh. and i even stripped the .c and .t of the test down to the single failing case... 18:47
i have a run of that simple example above in a windbg trace, but i haven't used windbg in about 15 years (and it didn't have time traveling support back then) 18:49
nine tonyo: 0xFFFF_FFFE is 0xFE sign extended to 32 bits 18:53
releasable6 Next release in ≈4 days and ≈23 hours. 1 blocker. Please log your changes in the ChangeLog: github.com/rakudo/rakudo/wiki/ChangeLog-Draft 19:00
tonyo you think NC is translating 0xFE to -2 then passing to C? 19:07
s/-2/signed int
i'm not seeing how you're thinking 0xFE turns into 0xFFFF_FFFE in the register 19:09
MasterDuke m: my int $int_min = -9223372036854775808; say $int_min + 1; # heh, this gives -9223372036854775809 for me... 19:16
camelia -9223372036854775807
MasterDuke m: my int64 $int_min = -9922337203; say $int_min; say $int_min + 1; # ha! and this gives -18446744063787214413 and -18446744063787214414 19:33
camelia -9922337203
MasterDuke a signed int is the same on windows as linux, right? am i going crazy? 19:34
tonyo yes 19:37
nine tonyo: when passing a char (aka signed int8) in a register extending 0xFE to 0xFFFFFFFE is absolutely correct and required by the platform ABI 19:58
And that makes sense as signed 8 bit 0XFE == -2 as is signed 32 bit 0xFFFFFFFE 19:59
Of course, sign extending is only correct if we're talking about a signed integer type 20:03
20:04 reportable6 left, linkable6 left, evalable6 left, unicodable6 left, notable6 left, committable6 left
nine tonyo: is this with dyncall or with libffi? 20:04
20:04 unicodable6 joined, notable6 joined, committable6 joined, linkable6 joined, reportable6 joined, evalable6 joined
tonyo it's happening with dyncall, no libffi here. 20:12
wonder if it's a problem in GCC too just masked by the architecture 20:13
nine Looks like the requirement to (sign) extend to 32 bit is even true for stack arguments. You can think of it like integer types smaller than 32 bit not actually being a thing in the x86_64 calling conventions (and presumably the same for the M1) 20:14
Well since extending to 32 bits is mandated by the ABI, the compiler is perfectly in its right to expect those values to be extended already and use them as is for e.g. 32 bit comparisions 20:15
20:16 lucs joined
nine tonyo: now I'm curious. Is the error still there with libffi? 20:23
tonyo well, gcc on x86_64 is using %dil which only compares the bottom byte 20:34
and %di for the bottom two
clang might be exposing the error by not using that shortcut on arm
nine yes, that's what I think
Now I wonder if we are doing it wrong or if its dyncall. So a look at libffi could narrow it down 20:35
tonyo gotcha, let me re find how to get libffi with rakudo on osx 20:52
with libffi, same issue 20:56
21:27 guifa joined
guifa What is the best way in nqp to scan along string? I’m wanting to do an index() for one of two separate values, and the best way for that ATM seems to be do just do two separate nqp::index() calls, but not sure if there might be a better way 21:28
tonyo you want to comb it or search for the second instance of something? 21:31
moon-child my interpretation was to search for the first instance of each of two things 21:36
[Coke] so given "abcdefgh" you want to find "bc" and "fg", e.g.? 21:38
guifa [Coke]: I’d want to find the first of either “bc” or “fg”, in that case, “bc” 21:39
[Coke] if so, yes, two index calls seems correct. if you care about ordering, you can use the first one's answer to cut the search space
guifa (although I’m only going ot be looking for a single character)
[Coke] then two indexs is probably faster than a regex. 21:40
lizmat that will be most certainly faster :-) 21:41
orders of magnitude
guifa Ah okay. I was thinking there should be a simple way to do something akin to 21:43
while($position < $length) { my $code = $string.code-at-offset($position); if $code == $a { … } elsif $code == $b { … } else { … } }
so that when I actually hit the first one it’ll stop doing extra comparisons
But two indexes works okay :-)
[Coke] You could try a walk through vs. 2 indexes; but there's no shortcut for it, I don't think. 21:44
21:45 LizBot joined
[Coke] might be worth it depending on your data, though (long strings, expecting an early find...) 21:45
guifa Probably pretty short strings tbh. I’m taking a look at github.com/rakudo/rakudo/issues/4322 and goign to write a formatter, and figured it a good chance to practice working with nqp 21:47
the time format strings have just two special characters to scan for, \ and %
lizmat guifa: perhaps the new sprintf implementation on the RakuAST branch could be an inspiration? 21:48
it just uses a grammar, though, but generates *code*, so the parsing would only need to be done once 21:49
guifa lizmat: that’s actually what I was looking at at first. DIdn’t realize it was generating code — I just knew sprintf is a bit more complicated, and assumed that compelxity justified the regex :-) 21:50
lemme see what I can stea—borrow 21:51
lizmat well, it would hook you into the rakuAST branch
so that means it wouldn't be readily available soon 21:52
guifa hmm, maybe I’ll do it twice. Learn NQP in round one, and learn RakuAST in round two ^_^
lizmat if you write your first attempt in such a way that you can EVAL a piece of code, then that would be more easily portable to RakuAST 21:53
afk& 22:04
guifa That’s what I did for the Intl version (for that reason, actually). If I were making EVAL code I could do this in like 5 minutes flat almost lol
22:45 linkable6 left, evalable6 left 22:46 linkable6 joined 22:47 evalable6 joined 23:36 guifa left