05:16
frost joined
07:02
frost left
08:33
frost joined
09:09
dakkar joined
09:47
frost left
09:48
frost joined
10:24
frost left
12:08
frost joined
12:50
frost left
13:01
frost joined
13:52
frost left
14:01
discord-raku-bot left
14:02
discord-raku-bot joined
15:16
A26F64 joined
15:22
MasterDuke left
15:32
frost joined
|
|||
A26F64 | A question or observation about subsets with `where` conditions. . . . It seems that checks for definedness in such cases fail. | 15:38 | |
m:subset S of Str; class C { has S $.foo; }; my $c = C.new; $c.foo ~~ S:U; # True | |||
m: subset S of Str; class C { has S $.foo; }; my $c = C.new; $c.foo ~~ S:U; # True | |||
camelia | ===SORRY!=== Regex not terminated. at <tmp>:1 ------> }; my $c = C.new; $c.foo ~~ S:U; # True⏏<EOL> Regex not terminated. at <tmp>:1 ------> }; my $c = C.new; $c.foo ~~ S:U; # True⏏<EOL> Couldn't find terminator… |
||
A26F64 | m: subset S of Str; class C { has S $.foo; } my $c = C.new; $c.foo ~~ S:U; # True | 15:39 | |
camelia | ===SORRY!=== Error while compiling <tmp> Strange text after block (missing semicolon or comma?) at <tmp>:1 ------> ubset S of Str; class C { has S $.foo; }⏏ my $c = C.new; $c.foo ~~ S:U; # True expecting any of: in… |
||
A26F64 | Something's not right with my example there. . . . | 15:40 | |
m: subset S of Str; class C { has S $.foo; }; my $c = C.new; $c.foo ~~ S; | 15:41 | ||
camelia | ( no output ) | ||
A26F64 | m: subset S of Str; class C { has S $.foo; }; my $c = C.new; say $c.foo ~~ S; | ||
camelia | True | ||
A26F64 | Good. | ||
m: subset S of Str; class C { has S $.foo; }; my $c = C.new; say $c.foo ~~ S:D; # False | 15:42 | ||
camelia | ===SORRY!=== Regex not terminated. at <tmp>:1 ------> y $c = C.new; say $c.foo ~~ S:D; # False⏏<EOL> Regex not terminated. at <tmp>:1 ------> y $c = C.new; say $c.foo ~~ S:D; # False⏏<EOL> Couldn't find terminator… |
||
A26F64 | m: subset S of Str; class C { has S $.foo; }; my $c = C.new; say $c.foo ~~ S:D; | 15:47 | |
camelia | ===SORRY!=== Regex not terminated. at <tmp>:1 ------> oo; }; my $c = C.new; say $c.foo ~~ S:D;⏏<EOL> Regex not terminated. at <tmp>:1 ------> oo; }; my $c = C.new; say $c.foo ~~ S:D;⏏<EOL> Couldn't find terminator… |
||
A26F64 | This is not going well, is it. It works locally. | 15:48 | |
m: class C { has Str $.f; }; my $c = C.new; say $c.f ~~ Str; | 15:51 | ||
camelia | True | ||
A26F64 | m: class C { has Str $.f; }; my $c = C.new; say $c.f ~~ Str:U; | ||
camelia | True | ||
A26F64 | m: class C { has Str $.f; }; my $c = C.new; say $c.f ~~ Str:D; | ||
camelia | False | ||
guifa | one issue of using S is that it's part of the switch syntax | ||
A26F64 | m: subset S1 of Str; class C { has S1 $.foo; }; my $c = C.new; say $c.foo ~~ S1; | 15:52 | |
camelia | True | ||
A26F64 | m: subset S1 of Str; class C { has S1 $.foo; }; my $c = C.new; say $c.foo ~~ S1:U; | ||
camelia | True | ||
A26F64 | m: subset S1 of Str; class C { has S1 $.foo; }; my $c = C.new; say $c.foo ~~ S1:D; | ||
camelia | False | ||
A26F64 | guifa, thanks. | ||
Anyway, those lack additional conditions. | |||
m: subset S1 of Str where * ~~ /^\dX$/; class C { has S1 $.foo; }; my $c = C.new; say $c.foo ~~ S1; # True | 15:53 | ||
camelia | True | ||
A26F64 | m: subset S1 of Str where * ~~ /^\dX$/; class C { has S1 $.foo; }; my $c = C.new; say $c.foo ~~ S1:U; # Error | ||
camelia | Use of uninitialized value of type Str in string context. Methods .^name, .raku, .gist, or .say can be used to stringify it to something meaningful. True in any at gen/moar/stage2/NQPCORE.setting line 1067 |
||
A26F64 | m: subset S1 of Str where * ~~ /^\dX$/; class C { has S1 $.foo; }; my $c = C.new; say $c.foo ~~ S1:D; # Error | ||
camelia | Use of uninitialized value of type Str in string context. Methods .^name, .raku, .gist, or .say can be used to stringify it to something meaningful. False in any at gen/moar/stage2/NQPCORE.setting line 1067 |
||
guifa | Aaaah I think I see the issue | 15:54 | |
think about what the where clause does | |||
when you say where * ~~ /^\dX$/, it needs to first run the regex | |||
which requires a concrete Str, which an undefined won't have | |||
Well, it should error on the first one then too | 15:55 | ||
m: subset S1 of Str where { $_ .defined ?? $ ~~ /^\dX$/ !! True }; class C { has S1 $.foo; }; my $c = C.new; say $c.foo ~~ S1:U | |||
camelia | True | ||
guifa | m: subset S1 of Str where { $_ .defined ?? $ ~~ /^\dX$/ !! True }; class C { has S1 $.foo; }; my $c = C.new; say $c.foo ~~ S1:D | 15:56 | |
camelia | False | ||
guifa | m: subset S1 of Str where { $_ .defined ?? $ ~~ /^\dX$/ !! True }; class C { has S1 $.foo; }; my $c = C.new; say $c.foo ~~ S1 | ||
camelia | True | ||
guifa | In any case, that works ^_^ (it ensures that the regex test is only done if it's defined, and otherwise, lets it pass, as presumably there's no difference between an undefined Str and an undefined S1) | 15:57 | |
A26F64 | Thanks; I guess that that makes sense. I've learned that there are numerous caveats involved with subsets so this an additional consideration. | 16:00 | |
Speaking of which: it also seems that (possibly for similar reasons) the `where` clause cannot use variables. | 16:02 | ||
m: subset S1 of Str where one(<foo bar>); # Success | |||
camelia | ( no output ) | ||
A26F64 | m: subset S1 of Str where <foo bar>.one; # Success | ||
camelia | ( no output ) | ||
A26F64 | m: my $s = <foo bar>; subset S1 of Str where one($s); # Failure | ||
camelia | ( no output ) | ||
A26F64 | Hm. | ||
m: my $s = <foo bar>; subset S1 of Str where one($s); my S1 $f = 'abc'; | 16:03 | ||
camelia | Type check failed in assignment to $f; expected S1 but got Str ("abc") in block <unit> at <tmp> line 1 |
||
A26F64 | Hm. | ||
m: my $s = <foo bar>; subset S1 of Str where one($s); my S1 $f = 'bar'; | 16:04 | ||
camelia | ( no output ) | ||
guifa | my @s = INIT <foo bar>; subset S1 of Str where one @s; my S1 $ = 'abc'; | ||
m: my @s = INIT <foo bar>; subset S1 of Str where one @s; my S1 $ = 'abc'; | 16:05 | ||
camelia | Type check failed in assignment; expected S1 but got Str ("abc") in block <unit> at <tmp> line 1 |
||
A26F64 | The assignment of something other than an element of $s fails in my instance. | ||
Sorry: I meant to say that the assignment of something other than an element of $s is allowed. | |||
guifa | That's odd. I don't think much has changed in subset handling over the past few months. What version of Rakudo do you have? | 16:07 | |
A26F64 | > $ raku --version | 16:08 | |
Welcome to Rakudo™ v2021.12. | |||
Implementing the Raku® Programming Language v6.d. | |||
Built on MoarVM version 2021.12. | |||
guifa | m: say $huh | 16:09 | |
camelia | ===SORRY!=== Error while compiling <tmp> Variable '$huh' is not declared at <tmp>:1 ------> say ⏏$huh |
||
guifa | err | ||
huh, that's weird. | |||
m: $*RAKU.compiler.version | |||
camelia | ( no output ) | ||
guifa | m: say $*RAKU.compiler.version | ||
camelia | v2021.12.213.g.05447137.f | ||
A26F64 | For me: | 16:10 | |
> say $*RAKU.compiler.version | |||
v2021.12 | |||
Copying the line that I posted above does return that type check error now, though. What was I doing differently before? Sorry for the confusion here. Let me review yet again. | 16:13 | ||
16:15
frost left
|
|||
A26F64 | For whatever reason running everything on one line seems to make a difference: | 16:16 | |
> my $s = <foo bar>; subset S1 of Str where one($s); my S1 $f = 'abc'; | |||
Type check failed in assignment to $f; expected S1 but got Str ("abc") | |||
in block <unit> at <unknown file> line 5 | |||
> my $s = <foo bar>; subset S2 of Str where one($s); | |||
(S2) | |||
> my S2 $f = 'abc'; | |||
abc | |||
guifa | it may be an idiosyncracy of the REPL | 16:20 | |
m: use MONKEY-SEE-NO-EVAL; EVAL ('my $s = <foo bar>; subset S2 of Str where one($s);' ~ "\n" ~ 'my S2 $f = "abc"; say $f') | 16:22 | ||
camelia | Type check failed in assignment to $f; expected S2 but got Str ("abc") in block <unit> at EVAL_0 line 2 in block <unit> at <tmp> line 1 |
||
guifa | yeah, it's likely a REPL issue | ||
A26F64 | Thanks. It's possible that I've only tried that in the REPL thus far; either way I really should confirm its behavior elsewhere. | 16:27 | |
I've also been wondering about signatures and types specified therein. (As you can see I'm very curious about typing matters.) For one thing: how best to explicitly (that is: beyond the use of a particular sigil) type positional arguments to functions? | 16:32 | ||
m: my List $p = (4, 2); sub f1(@v) { say @v.WHAT; say @v; }; f1($p); # Argument is untyped List (with @ sigil) | |||
camelia | (List) (4 2) |
||
A26F64 | m: my List $p = (4, 2); sub f2($v) { say $v.WHAT; say $v; }; f2($p); # Argument is untyped List (with $ sigil) | ||
camelia | (List) (4 2) |
||
A26F64 | m: my List $p = (4, 2); sub f3(Int @v) { say @v.WHAT; say @v; }; f3($p); # Error: @v expected to be an array of Lists | ||
camelia | ===SORRY!=== Error while compiling <tmp> Calling f3(List) will never work with declared signature (Int @v) at <tmp>:1 ------> ub f3(Int @v) { say @v.WHAT; say @v; }; ⏏f3($p); # Error: @v expected to be an ar |
||
A26F64 | m: my List $p = (4, 2); sub f4(Int $v) { say $v.WHAT; say $v; }; f4($p); # Error: $v expected to be an Int | ||
camelia | ===SORRY!=== Error while compiling <tmp> Calling f4(List) will never work with declared signature (Int $v) at <tmp>:1 ------> ub f4(Int $v) { say $v.WHAT; say $v; }; ⏏f4($p); # Error: $v expected to be an In |
||
A26F64 | (Actually, f3 is expecting an array of Ints, I think. But it's getting a List.) | 16:33 | |
guifa | Correct | ||
A26F64 | But it would be useful for the function to know the type of the contents of the positional that it's expecting. | 16:35 | |
I think that someone recently argued that those types should be specified on variable creation as it's not efficient to test in the signature on every call. | |||
guifa | Correct.Type checking is done very shallowly in Raku. for something like sub foo(Int @bar), it asks the argument "Are you an Array? Cool. Do you require your elements to be Ints? Awesome, I'll let you in" | 16:36 | |
A26F64 | If I understood that correctly. But that does seem like a fairly ordinary thing to specify in the signature. | ||
guifa | actually, I lie. the @bar asks "Are you positional? Cool. Do you require your elements to be Ints? Awesome, I'll let you in" | 16:37 | |
When you pass the list, the answer is "Yes" and then "No", so it fails | |||
sub foo( @bar where .all ~~ Int ) asks the questions, "Are you positional? Does every single one of your elements type check as an Int?". The problem is then that you need to check, individually, whether each element is an Int | 16:39 | ||
That's fine for a few elements, but if you're regularly passing lists with thousands of items, that check will really slow things down. | |||
One solution you can do is | |||
m: multi sub foo(Int @bar) { say "type check succeeded for {@bar}" }; multi sub foo(@bar) { say "trying to convert {@bar}"; foo (my Int @ = @bar); }; my Int @a = 1,2,3; my @b = 4,5,6; my @c = <a b c>; foo @a; foo @b; foo @c; | 16:44 | ||
camelia | type check succeeded for 1 2 3 Type check failed in assignment to @; expected Int but got Str ("a") in sub foo at <tmp> line 1 in block <unit> at <tmp> line 1 trying to convert 4 5 6 type check succeeded for 4 5 6 trying to convert … |
||
guifa | okay, so the error message got there faster than the regular test haha | ||
lemme take off the last one | |||
m: multi sub foo(Int @bar) { say "type check succeeded for {@bar}" }; multi sub foo(@bar) { say "trying to convert {@bar}"; foo (my Int @ = @bar); }; my Int @a = 1,2,3; my @b = 4,5,6; foo @a; foo @b; | 16:45 | ||
camelia | type check succeeded for 1 2 3 trying to convert 4 5 6 type check succeeded for 4 5 6 |
||
guifa | By using a multi, you get the best of both worlds. If you've strongly typed your positional as an Int, you get O(1) type checking. If not, you get O(n) checking | 16:46 | |
and if you pass something else, it will error, although the location of the error will be slightly off (the message will be correct though) | 16:47 | ||
A26F64 | I see what you mean by characterizing the check as "shallow". But it does seem to be an appropriate strategy at least for the purposes of efficiency. | 16:50 | |
And it does encourage consistency in assigning types throughout the code. | |||
I admit that at least a small part of my uncertainty is related to the fact that $-sigilled variables can contain positional structures and that they can (as in my first example above) be converted to @-sigilled variables via the signature. | 16:53 | ||
I understand the notion of a List as a single structure and therefore appropriate for a $ variable but I have wondered about the maintaining consistency of those sigils. | 16:55 | ||
guifa | I always think of it as you have a $bag and you have a @bag. In the former, I care about the bag-as-container, and the latter, I care about the bag's contents. It's still the same bag, though. | ||
A26F64 | Right. Except when you pass $bag to a function and it becomes @bag inside. So it no longer looks like the same kind of container. | 16:56 | |
guifa | Sure, but that's where the function is expressing its concern over the contents, rather than the container. In terms of type checking | 16:57 | |
sub foo ( Int @bar ) is basically the same as sub foo ( Array[Int] $bar ) | 16:58 | ||
(basically because it's not 100% accurate, but close enough for this discussion) | |||
You can pass the same bag around, and each person can decide whether they care about it as a container, or its contents, without worrying about how others deal with it. | 17:01 | ||
A26F64 | Which I guess is a feature once you accept that fact of flexibility. | 17:02 | |
guifa | Yeah. I mean, in your own code, if you want to treat everything with a $ sigil, you can. Quite a few people do that coming from other languages, actually | 17:04 | |
In my modules, I can use @, %, and & as well, and it doesn't affect your code, even if you interact with my modules | 17:05 | ||
Raku gives you a lot of ways to be expressive in code, but notably, they aren't generally required. Just optional. | 17:06 | ||
A26F64 | Of course I do appreciate the options and much else with respect to expressivity. | ||
Thank you very much for your attention and insight. I actually have a few other observations (some---not too surprisingly, perhaps---about types and subsets) but I'll reserve them for later and not take up too much more time. | 17:07 | ||
guifa | Feel free to ask away :-) That's what we're here for. I've got to head to $day-job, but hopefully others can answer (if you stay connected, someone almost always will answer, it just might be delayed by an hour or two if they're afk) | 17:08 | |
A26F64 | Indeed; this channel has in general been an excellent resource. | 17:09 | |
17:31
dakkar left
17:43
A26F64 left
20:02
discord-raku-bot left,
discord-raku-bot joined
|