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