🦋 Welcome to Raku! raku.org/ | evalbot usage: 'p6: say 3;' or /msg camelia p6: ... | irclog: colabti.org/irclogger/irclogger_log/raku
Set by ChanServ on 14 October 2019.
japhb Is there an idiom for calling 'submethod TWEAK' for all *roles* composed into a class? Right now I've got a hack role that I compose into some class in my inheritance hierarchy -- role RoleTweaking { method TWEAK_ROLES(|c) { for self.^roles { my $method = .^lookup("TWEAK"); self.$method(|c) if $method; } } } -- and then call self.TWEAK_ROLES from that class's submethod TWEAK. 05:53
But that feels like a workaround for something I would expect to Just Work. 05:54
Plus there's no guarantee that I will remember to only call TWEAK_ROLES from *one* class in the hierarchy, unless I make some convention like only ever calling it from the base class -- but that means it will be called before any other class TWEAKs in the inheritance tree, even if the TWEAKed roles are only composed into a leaf class. 05:55
(Only ever calling it from *leaf* classes has the problem that leaf classes don't always stay that way -- inherit from one and forget it was once a leaf that called TWEAK_ROLES, and suddenly you're likely to call it twice again.) 05:56
japhb Ugh, it occurs to me that RoleTweaking has yet another problem -- it assumes that no class in the hierarchy only composed *ONE* other role, and thus called its TWEAK normally because it was composed in without conflict. 06:03
GAH
japhb After some more thought, it occurs to me that there's no conflict if role submethods have a name extension based on the role name. So for example: role Foo { submethod TWEAK-Foo { ... } }; role Bar { submethod TWEAK-Bar { ... } }. Then it is certain that these TWEAK-related submethods will not be called automatically, which means they can be called from a TWEAK_ROLES that looks up methods to call as 07:09
follows: for self.^roles { my $method = .^lookup('TWEAK-' ~ .^name); ... }
I suppose you could even do that with the class-defined TWEAK submethods, and then walk the .^mro and .^roles(:local) from each to force the whole thing to happen in C3 order. 07:11
Still really feel like I'm overthinking this though ....
wbiker Hello all 09:45
Anyone familiar with Test::Mock? I want to use a mock of a class where a method is called twice from the code under test. Is there a way to configure the returning that for each method call another string is given back?
This returns an array instead:
my $mock = mocked MyClass::Client, returning => { get => "Return String One", "Return String Two" };
CIAvash wbiker: in that line your'e saying that method `get` on `MyClass::Client` returns list `"(Return String One", "Return String Two") ` (should be in parens) 11:46
wbiker: I don't know what you're doing or how you're testing but you can do `my $strings = ("Return String One", "Return String Two").iterator; my $mock = mocked MyClass::Client, computing => { get => { $strings.pull-one }};` 11:47
wbiker Cool. Thanks @CIAvash I think that it what I was looking for. Using a iterator here! 11:49
uzl[m] m: .say for &comb.candidates>>.signature 15:39
camelia (Regex $matcher, Cool $input, $limit = *, :$match)
(Str $matcher, Cool $input, $limit = *)
(Int:D $size, Cool $input, $limit = *)
tellable6 2020-05-30T08:15:37Z #raku-dev <JJMerelo> uzl[m] OK, done, but please include closing statements in the PRs and/or commits you're doing for them in the future. 15:40
uzl[m] m: .say for &base.candidates>>.signature
camelia 5===SORRY!5=== Error while compiling <tmp>
Undeclared routine:
base used at line 1
uzl[m] How do I get a method's candidates' signatures?
uzl[m] m: .say for Real.^methods.first(*.name eq 'base').candidates>>.signature 15:44
camelia ($?CLASS: Int:D $base, $digits? is copy, *%_)
uzl[m] Oh found it haha
codesections can anyone explain these results? I'm confused: 16:01
m: use nqp; my int $a = 0; say nqp::isint(nqp::unbox_i($a)); say nqp::isint($a)
camelia 0
0
MasterDuke it only work in real nqp-land 17:23
nqp: my int $a := 0; say(nqp::isint(nqp::unbox_i($a))); say(nqp::isint($a))
camelia 1
1
xinming_ m: (<x y> => "test").raku.say; 18:18
camelia ("x", "y") => "test"
xinming_ m: Pair.new(:key(<x y>), :value<test>).raku.say; 18:19
camelia $("x", "y") => "test"
xinming_ How can we use Pair.new syntax to create a pair which the key is a List?
I mean, without the $() 18:20
summerisle m: Pair.new(:key<x y> :value<z>).key.WHAT
camelia ( no output )
summerisle m: Pair.new(:key<x y> :value<z>).key.WHAT.say
camelia (List)
summerisle m: Pair.new(:key<x y> :value<z>).key.say 18:21
camelia (x y)
summerisle m: Pair.new(:key(<x y>) :value<z>).key.WHAT.say
camelia (List)
summerisle m: Pair.new(:key(<x y>) :value<z>).key.say
camelia (x y)
summerisle seems fine to me
xinming_ summerisle: What I mean is, the output should be the same as ("x", "y") => "test" :-) 18:26
uzl[m] m: Pair.new(:key(<x y>) :value<z>).key.raku.say 18:27
camelia ("x", "y")
uzl[m] m: Pair.new(:key(<x y>) :value("test")).key.say
camelia (x y)
summerisle on rakudo v2021.02, :key(<x y>) and :key<x y> (which should be directly equivalent) both seem to create a pair with a non-scalar key, so
i'd say it's working as you expect
codesections xinming_: you can use positional args: 18:28
m: Pair.new(<x y>, 'z').raku.say
camelia ("x", "y") => "z"
codesections MasterDuke: Thanks. I'd forgotten about *real* nqp land :D 18:29
codesections m: sub f( --> (Int, Int)) { 42, 47 } 21:04
camelia 5===SORRY!5=== Error while compiling <tmp>
Malformed return value
at <tmp>:1
------> 3sub f( -->7⏏5 (Int, Int)) { 42, 47 }
codesections is there any way to dwim ^^^^? 21:04
codesections Or is that the usecase that needs to wait for lizmat's work on tuples? 21:08
gfldex m: subset ListOfInt of List where { .all ~~ Int }; sub f( --> ListOfInt ) { 42, 47 } 21:24
camelia ( no output )
gfldex m: subset ListOfInt of List where { .all ~~ Int }; sub f( --> ListOfInt ) { 42, 47 }; f;
camelia ( no output )
gfldex m: subset ListOfInt of List where { .all ~~ Int }; sub f( --> ListOfInt ) { 42, 47 }; say f;
camelia (42 47)
gfldex codesections: ^^^ you can make the subset as strict as you need
codesections Hmmm, yeah. But that's not really in the spirit of what I want -- `f(--> Int)` is a constraint, but it's also using types as concise API documentation that &f always returns a single Int. I'd like to be able to say "f always returns a pair of two Ints" in the type system, but that's only worth doing if the syntax is there to say it naturally 21:29
but thanks, gfldex, that's helpful & appreciated 21:31
gfldex codesections: subsets can be exported. That way you can allow the user of your API to use them in their code. This can be quite helpful to avoid typos and bad copy pasta. 21:42
codesections Yeah, I get that :-) And I like and use subsets
But that's a different usecase than "function signature as documentation" 21:43
(though with some overlap, to be sure)
lizmat codesections: I don't think this has anything to do with my Tuple module ? 22:45
codesections Oh, ok. I wasn't sure/haven't followed that module closely. In some languages, you'd say that a function with the signatur of f(Int --> (Str, Int)) "takes an Int and returns a Tuple of one Str and one Int". So I was wondering if better support for tuples would be related somehow. But I guess my guess was wrong :) 22:49
lizmat I guess my Rake module gets closer to that 22:54
modules.raku.org/dist/Rake 22:55
guifa Oof 23:17
One good thing about me now creating all of these moduels based around the CLDR is I’m finding how some of my earlier modules sucked :-)
Namely the LanguageTag which needs … a lot of work
codesections .tell vrurg I just had my first occasion to use the new COERCE method, and it's *really* nice. Thanks for your work adding that :) 23:46
tellable6 codesections, I'll pass your message to vrurg
vrurg codesections: you're welcome! :) 23:46
vrurg can't still believe it all started as a fix for an old github issue... 23:47