🦋 Welcome to the MAIN() IRC channel of the Raku Programming Language (raku.org). Log available at irclogs.raku.org/raku/live.html . If you're a beginner, you can also check out the #raku-beginner channel!
Set by lizmat on 6 September 2022.
00:02 yewscion joined 00:07 yewscion left 00:08 Guest72 left, Guest72 joined 00:10 yewscion joined 00:16 yewscion left 00:44 [Coke]_ joined 00:46 [Coke] left 00:58 yewscion joined 01:06 yewscion left 01:08 topnep left 01:10 topnep joined 01:12 yewscion joined 01:17 yewscion left 01:43 marcprux joined 01:45 marcprux left 02:00 hulk joined, kylese left 02:15 hulk left, kylese joined 02:19 Guest72 left 02:31 yewscion joined 02:36 yewscion left 02:54 yewscion joined 02:59 yewscion left 03:35 Aedil joined 03:45 kylese left 03:46 Guest72 joined 03:47 kylese joined 05:10 arkiuat left 05:40 arkiuat joined 05:45 Sgeo left 05:49 arkiuat left 05:55 pony left 06:02 arkiuat joined 06:06 arkiuat left 06:35 arkiuat joined 06:39 arkiuat left 06:43 human-blip left, human-blip joined 06:59 Aedil left 07:09 arkiuat_ joined 07:14 arkiuat_ left 07:18 Aedil joined 07:20 librasteve_ joined 07:42 arkiuat_ joined 07:44 Aedil left 07:46 arkiuat_ left 07:49 Aedil joined 07:54 arkiuat_ joined 07:58 wayland joined 08:11 dakkar joined 08:20 lichtkind joined 08:46 human-blip left 08:48 human-blip joined 08:59 arkiuat_ left 09:02 human-blip left 09:03 human-blip joined 09:45 arkiuat joined 09:50 librasteve_ left, arkiuat left 09:55 arkiuat_ joined 10:57 arkiuat_ left 11:09 arkiuat_ joined 11:14 arkiuat_ left 11:30 tgt joined 11:32 tgt left 11:34 tgt joined 11:43 tgt left, arkiuat_ joined, tgt joined 11:48 arkiuat_ left 11:51 tgt left 12:09 apac joined 12:10 arkiuat_ joined 12:13 [Coke]_ is now known as [Coke], wayland left, wayland76 joined 12:15 arkiuat_ left 12:29 arkiuat_ joined 12:31 librasteve_ joined 12:57 yewscion joined 12:58 arkiuat_ left 13:06 apac left 13:10 Guest72 left 13:25 arkiuat joined
[Coke] new/BUILD/TWEAK - I have an attribute that's an array. I want to have a constructor that takes a string, and use an internal method to populate the attribute from the string. I am confused about which of new/build/tweak are needed here. 16:04
tbrowder i do that same thing and i use TWEAK. in fact, i think i use TWEAK almost all the time. not much THINKING required 😆 16:12
[Coke] You still need a new, yes? 16:14
otherwise you get errors about default constructor
tbrowder arkiuat: pls check out my two doc PRs and add any comments needed to address yr two doc issues 16:15
yes, i do use the .new
[Coke] You have git URL I can check out? 16:16
librasteve i also prefer TWEAK
tbrowder i think i have one in work…. 16:17
need it soon?
[Coke] eh, I'll probably figure it out by then. 16:18
tbrowder probably, but looking now
[Coke] (This exercise is making we want to update the object tutorial. :| 16:21
tbrowder check out github.com/tbrowder/RakuDoc-Utils/ 16:22
look in lib/…/Subs.rakumod
ab5tract [Coke]: TWEAK more or less subsumes BUILD for most use cases, but it sounds like for your case BUILD might actually be nicers
tbrowder class Atom 16:23
[Coke] tbrowder: that has both attrs and style as attributes.
ab5tract because you can just make sure that your attribute assembler returns a hash, then slip that 16:24
tbrowder yes, it’s a WIP
[Coke] I want to take the initialization string, process it, then pretend it didn't exist.
ab5tract: any pointers to a BUILD example that does that?
ab5tract not off the top of my head but let me take a look 16:25
hmm, actually maybe that use case is even best served in new 16:26
[Coke] this is some serious yak shaving, btw. I was trying... to solve a sudoku. :)
ab5tract :)
tbrowder yeay, BUILD is maybe better, or in yr own defined new
ab5tract so yeah, the pattern I had in mind is best served by new, where you slip the processed hash result into the self.bless call 16:27
tbrowder i did ask for you as reviewer for 2 doc PRs 16:28
afk&
[Coke] ok, got there with new.
ab5tract nice :) 16:29
Voldenet whenever I need custom logic, I simply make my own .new, I feel like it's closer to the constructor from other languages 16:34
[Coke] ok, got past the *errors*. now if I do new { my @a = parse-string($strign); self.bless(:board(@a)), looks like the data isn't being stored.
16:35 dakkar left
Voldenet m: class X { has @.board; method new(Int $x) { my @x = $x; self.bless(:board(@x)) } }; X.new(42).say # e.g. 16:35
camelia X.new(board => [42])
[Coke] ... I'm an idiot. Thank you. Still had some scaffolding in there to get a compilation that I needed to remove now that it's compiling. 16:37
Voldenet thing I never get how to actually use is BUILD 16:38
[Coke] ok. NOW I think that the new isn't setting the attribute. 16:45
16:45 jjido joined
ab5tract Voldenet: That's why TWEAK superseded BUILD for most use cases. You don't have to worry about the signature and all of the attributes will have been set up 16:45
[Coke] I'll golf it at some point. :( 16:46
Voldenet in fact, the same thing I've noticed when using records in C# - a lot of times I prefer to create static method that actually sets all the fields instead of having N constructors
ab5tract [Coke]: well, technically the attributes are set via the bless call 16:47
so at least to some degree the statement "new isn't setting the attribute" is true. But that's borderline pedantic, as I assume you mean the "approach using new" 16:48
[Coke] ending new with self.bless.... 16:49
(similar to voldenet's example above)
Voldenet might not work with privates
ab5tract right, so one other thing to keep in mind is that if you are getting the data from MAIN, $x will be a string
Voldenet m: class X { has @!board; method new(Int $x) { my @x = $x; self.bless(:board(@x)) } }; X.new(42).say 16:50
camelia X.new
Voldenet m: class X { has @!board is built; method new(Int $x) { my @x = $x; self.bless(:board(@x)) } }; X.new(42).say
camelia X.new(board => [42])
[Coke] is built has changed the error message, at least. :)
ab5tract nice :)
Voldenet ab5tract: TWEAK feels more like "initialize" method that most languages are missing 16:51
and C# ends up doing things like `interface IInitializable { void Initialize(): }` 16:52
which is not very beautiful
it's even more pain when you need to do async in constructor
[Coke] yay, my dumb example now works, and now I have no desire to make the actual problem work. :)
I imagine you'd have to do the callback *first*, and then feed that into an object constructor. (rather than starting to construct and then trying to do a callback from inside new or something) 16:54
ab5tract hmm, I don't know why that would matter off the top of my head 16:57
16:58 librasteve_ left
Voldenet wrong initialization order perhaps 17:01
[Coke] ab5tract: well if you're not awaiting the result, ... what state is the object in after you call new?
ab5tract m: 13:01 <ab5tract> m: class C { has @!x is built; has @!y is built; method new(Str $s, &c) { self.bless: | c($s) } }; dd C.new: "ok|dok", -> $s { my @sp = $s.split("|"); %( :x(@sp[0]), :y(@sp[1]) ) }
camelia ===SORRY!=== Error while compiling <tmp>
Confused
at <tmp>:1
------> 13:<HERE>01 <ab5tract> m: class C { has @!x is bu
expecting any of:
colon pair
ab5tract m: class C { has @!x is built; has @!y is built; method new(Str $s, &c) { self.bless: | c($s) } }; dd C.new: "ok|dok", -> $s { my @sp = $s.split("|"); %( :x(@sp[0]), :y(@sp[1]) ) } 17:02
camelia C.new(x => ["ok"], y => ["dok"])
[Coke] Do you have an attribute like $.usable that you trigger off if the callback isn't done?
ab5tract you can return a failure instead of calling self.bless 17:03
but that does honestly sound more complicated than what I would put into a constructor
Voldenet the example feels like it's really trying to touch internals too much 17:05
m: class C { has @!x is built; has @!y is built; }; dd { my @sp = "ok|dok".split("|"); C.new( :x(@sp[0]), :y(@sp[1]) ) }() 17:07
camelia C.new(x => ["ok"], y => ["dok"])
ab5tract Voldenet: this is contrived
For a sudoku solver, you could imagine processing a string
17:07 yewscion left
Voldenet I mean, I wouldn't really let outer callback use internal field names, it feels scary to maintain 17:07
I'd rather make a separate sub out of it 17:08
ab5tract Voldenet: I agree. I was just demonstrating that there is nothing inherent to stop this from working
Voldenet ah, that's true 17:09
as long as bless gets proper args, it'll work
ab5tract but yeah, I wouldn't ever do this kind of processing unless it was stable enough to put into a dedicated sub
Voldenet now that I think of it, in most cases clever logic in the ctor was promoting the class into higher order being that had to be refactored into separate factories/validators at some point 17:26
ab5tract the ctor? 17:29
I'm intrigued :)
Voldenet I mean constructor
ab5tract Ah, gotcha. c9r :) 17:30
I like this idea of being promoted to a higher order being though. Is there a waiting list I can sign onto? :) 17:31
Voldenet sorry, god classes worship queue is now full of sleep-deprived mainainers, can't enqueue more ;) 17:32
ab5tract Also, we have the tiny bits to ensure that any callback is conformant to the requirements of the class attributes
Still doesn't make it a brilliant idea, I think, but it's still kind of cool that we can get there with subsets 17:33
hmmm: subset OutShape where { .keys.sort ~~ <x y> }; subset SigShape of Callable where { .signature ~~ :(Str --> OutShape) }; sub s(Str $s --> OutShape) { %( :x, :y ) }; dd &s ~~ SigShape 17:37
lol
m: subset OutShape where { .keys.sort ~~ <x y> }; subset SigShape of Callable where { .signature ~~ :(Str --> OutShape) }; sub s(Str $s --> OutShape) { %( :x, :y ) }; dd &s ~~ SigShape 17:38
camelia Bool::True
Voldenet m: subset OutShape where { .keys.sort ~~ <x y> }; subset SigShape of Callable where { .signature ~~ :(Str –> OutShape) }; sub s(Str $s –> OutShape) { %( :x, :z ) }; dd &s ~~ SigShape 17:41
camelia ===SORRY!=== Error while compiling <tmp>
Malformed parameter
at <tmp>:1
------> of Callable where { .signature ~~ :(Str<HERE> –> OutShape) }; sub s(Str $s –> OutShap
expecting any of:
constraint
formal parameter
Voldenet m: subset OutShape where { .keys.sort ~~ <x y> }; subset SigShape of Callable where { .signature ~~ :(Str --> OutShape) }; sub s(Str $s --> OutShape) { %( :x, :z ) }; dd &s ~~ SigShape
camelia Bool::True
Voldenet not as planned, I suppose 17:42
of course, s will return wrong type, but you can only find out when getting a runtime error after the fact 17:43
and even if compiler was smart enough to validate attributes (which is possible), it probably won't be smart enough to validate that 17:44
17:45 notna joined
Voldenet otoh 17:47
m: class OutShape { has $.x; has $.y; }; sub s(Str $s --> OutShape) { OutShape.new(:x, :y) }; dd &s.signature ~~ :(Str $s --> OutShape)
camelia Bool::True
ab5tract yeah that's a good one
Voldenet maybe it's not as clever, but it's very obvious
ab5tract I think it's better on all fronts 17:48
but TMMYTD
jeez I just butchered that (is there more than one acronym to "do it"? :)
.seen TimToady 17:49
tellable6 ab5tract, I saw TimToady 2021-11-10T02:17:00Z in #raku: <TimToady> Thanks!
Voldenet there's more than one way to write timtowdi
...timtowtdi 17:50
ab5tract :) 17:54
18:02 jjido left 18:06 _________ left 18:08 _________ joined
ab5tract Voldenet: also, there's something really interesting going on WRT runtime vs compile time checking.. observe this sorry: 18:10
m: subset OutShape where { .keys.sort ~~ <x y> }; subset SigShape of Callable where { .signature ~~ :(Str --> OutShape) }; sub s(Str $s --> OutShape) { %( :z, :y ) }; s()
camelia ===SORRY!=== Error while compiling <tmp>
Calling s() will never work with declared signature (Str $s --> OutShape)
at <tmp>:1
------> s(Str $s --> OutShape) { %( :z, :y ) }; <HERE>s()
ab5tract m: subset OutShape where { .keys.sort ~~ <x y> }; subset SigShape of Callable where { .signature ~~ :(Str --> OutShape) }; sub s(Str $s --> OutShape) { %( :z, :y ) };
camelia ( no output )
ab5tract So it does fail at compile time, but only when there is an attempt made to call the sub 18:11
18:20 jjido joined, notna left 18:24 Aedil left 18:37 Aedil joined 18:49 apac joined 18:59 Guest72 joined 19:01 yewscion joined
Voldenet m: subset OutShape where { .keys.sort ~~ <x y> }; subset SigShape of Callable where { .signature ~~ :(Str –> OutShape) }; sub s(Str $s –> OutShape) { %( :z, :y ) }; s("blah") # but for a different reason 19:01
camelia ===SORRY!=== Error while compiling <tmp>
Malformed parameter
at <tmp>:1
------> of Callable where { .signature ~~ :(Str<HERE> –> OutShape) }; sub s(Str $s –> OutShap
expecting any of:
constraint
formal parameter
19:01 stanrifkin joined
Voldenet m: subset OutShape where { .keys.sort ~~ <x y> }; subset SigShape of Callable where { .signature ~~ :(Str --> OutShape) }; sub s(Str $s --> OutShape) { %( :z, :y ) }; s("blah") # but for a different reason 19:01
camelia Type check failed for return value; expected OutShape but got Hash ({:y(Bool::True), :z(...)
in sub s at <tmp> line 1
in block <unit> at <tmp> line 1
Voldenet it's just a runtime error if you call s with string 19:02
ab5tract Ah, excellent catch 19:20
It didn’t seem fathomable how the return type checking would have been working at compile time there 19:21
20:07 Aedil left 20:16 Aedil joined 20:28 yewscion left 20:47 FrankTheTank358 joined 20:48 Aedil left
arkiuat tbrowder: done 20:53
21:08 FrankTheTank358 left 21:35 jjido left 21:45 apac left
arkiuat tbrowder: oh, that was just the first one. Both are done now. 22:03
22:03 stanrifkin left, Guest72 left, Guest72 joined 22:08 yewscion joined
tbrowder thank you! 22:11
22:13 yewscion left
arkiuat and thank you! 22:13
tbrowder ok, brief look. main prob i have that caused you some problem is the link i gave. it's easy for me to get confused when getting proper wikipedia links for a article. so i'll check again more carefully. the rest i need some more time to edit a bit. and maybe add a bit more detail, adding a bit from yr proposed example. 22:38
wayland76 .tell [Coke] (and ab5tract) With the .new method, instead of calling self.bless, you'd be better off using "callsame" or "callwith". That'll call the next .new down the chain, eventually getting to Mu.new which will call bless anyway. 22:41
tellable6 wayland76, I'll pass your message to [Coke]
22:41 yewscion joined
ab5tract wayland76: I don't know if "better off" is the correct wording, considering I have never seen that nor needed it 22:41
but its a cool trick to note, regardless 22:42
Voldenet I don't enjoy callsame/callwith and friends
tbrowder the two issues are related, in my opinion, because of my my view of the **practical** use of the .julian-date, but i'll consider yr points more closely. 22:43
wayland76 ab5tract: Yes, It's not actually necessary, but I think it's a better habit, because otherwise the .new method on any ancestor classes will get skipped.
Voldenet: Why not? Are they confusing? (I updated the docs because they were) Do you think the performance is bad? 22:44
Voldenet to me it feels like I don't know what I'm actually dispatching
I get how that's the whole point of it
wayland76 Oh! Right. Yes, that's true. It's a DWIM thing. 22:45
And, now that I think about it, I think I really only use it in .new most of the time.
Voldenet I guess it's a habit, because I've been in C# world too long, where the language makes things verbose
wayland76 Yeah, I can see that. 22:46
Voldenet there is base(…) constructor which is kinda similar
but inheritance is usually not very useful
wayland76 In Raku, or in C#? 22:47
Voldenet well, in C#, in raku a lot of features work because of it
22:48 yewscion left
Voldenet a lot of people in C# prefer composition, I'm not sure if there's practical reason for it other than "it's not stylish now" 22:48
wayland76 For me, callsame/callwith are just a slightly different way of saying parent::new (or whatever it is). 22:49
Voldenet actually in raku composition-based style works especially well because of `trait handles` 22:50
ab5tract wayland76: in Java it's super()
wayland76 .tell [Coke] (or nextsame/nextwith, depending on what you're doing)
tellable6 wayland76, I'll pass your message to [Coke]
ab5tract I don't tend to do much inheritence, roles generally fit better, but it's a great thing to consider wayland76++ 22:51
wayland76 I guess I see callsame/callwith as being like "Carry on doing what you would've been doing had I not been here".
tbrowder arkiuat: i will wo
Voldenet but wait, can you actually replace self.bless with callwith somehow?
m: class C { has @!x is built; method new($x) { callwith(x=>$x) }}; C.new(42).say 22:52
camelia C.new(x => [42])
wayland76 Hmm. I wonder if callsame/callwith are better for working with roles than the parent::new or whatever.
Voldenet hm, interesting, I'd think that since new wasn't multi, it wouldn't work
ab5tract If I see a method new in a role, I cry
tbrowder *work on it tomorrow
22:55 Guest72 left
wayland76 Voldenet: I think I saw some discussion about this at one point that cued me that it's not specific to multis, it's actually "the next method if I weren't here". 22:55
22:55 Sgeo joined
ab5tract between new/BUILD/TWEAK and self.bless/callsame/callwith/nextsame/nextwith, I think we can say Raku achieves sufficient complexity in its constructors 22:55
Voldenet ^ true, and the complexity isn't very well communicated imo 22:56
wayland76 Actually, found it: docs.raku.org/language/functions#Re-dispatching That first paragraph in Re-dispatching lists 3 options for the chains of functions we could be working with.
22:56 Guest72 joined
wayland76 Actually, I wonder sometimes if we don't need BUILDARGS (cf. P5 Moose) and POST-TWEAK, which only happens after the construction is complete. 22:57
Voldenet there was a time where I was lacking "use X by default, use Y in case where something, use Z in case where something" sort of guideline
wayland76 Anyway, I've got to head to work now. o/ 22:58
22:58 wayland76 left
ab5tract I think TWEAK already implies that construction is complete 23:00
Voldenet I don't think it's sufficient complexity though, C++ has more 23:01
it's my gold standard for making constructors scary
23:02 Xliff joined
Xliff \o 23:02
tellable6 2025-05-20T07:20:16Z #raku <librasteve> Xliff: on Emmet lol
ab5tract m: class C { has $.h = builded; sub builded { "hoi" }; submethod TWEAK { dd $!h } }; C.new
camelia $!h = "hoi"
Xliff librasteve: ROFLMAO
m: say <a b c> »Z» (1, 2) 23:03
camelia ===SORRY!=== Error while compiling <tmp>
Missing infix inside hyper
at <tmp>:1
------> say <a b c> »Z»<HERE> (1, 2)
expecting any of:
infix
infix stopper
Xliff m: say <a b c> Z (1, 2)
camelia ((a 1) (b 2))
Xliff O_o? Z is not infix?
ab5tract syntactically, sure 23:04
Xliff But not technically?
ab5tract no, because it is not a sub
Voldenet TWEAK kinda happens durring self.bless, so you could argue that it's happening during the construction 23:05
Xliff m: say <a b c> »x» (1, 2)
camelia (a bb c)
Xliff m: say <a b c> »X» (1, 2)
camelia ===SORRY!=== Error while compiling <tmp>
Missing infix inside hyper
at <tmp>:1
------> say <a b c> »X»<HERE> (1, 2)
expecting any of:
infix
infix stopper
ab5tract x and X are not related
Xliff However X and Z are?
Voldenet m: class C { has $.h = builded; sub builded { "hoi" }; submethod TWEAK { dd $!h }; method new() { say "pre"; self.bless; say "post" } }; C.new
camelia pre
$!h = "hoi"
post
ab5tract yes.. they are two of the three meta operators
Xliff Ah, so metaops don't hyper? 23:06
ab5tract Voldenet: that makes sense. I would fight interminably hard against the introduction of anything else into constructor land though 23:07
with RakuAST it would be relatively trivial to enforce self.bless being the final line in any new method, but that's arguably not the answr here
Voldenet it can be endlessly extended, but because self.bless is not the final line, nothing stops you from doing any post-tweaking 23:08
Xliff ab5tract: So the message is a bit LTA. Couldn't it be something like 'Cannot use a metaop in a hyper operation'?
ab5tract Xliff: no, metaops don't hyper. but what you are doing isn't really hypering, unless I misrmember
Xliff m: say <a b c> Z (1, 2) 23:09
camelia ((a 1) (b 2))
23:09 lichtkind left
Xliff I'd be fine if the output there was ((a 1) (b 2) (c 1)) because the Z would wrap around the list. »Z« would if it were allowed. 23:09
23:10 nicole left
ab5tract Xliff docs.raku.org/routine/roundrobin 23:12
Xliff ab5tract: Oh. So that 23:13
Voldenet Z is a metaop, so you gotta give an op
m: say <a b c> >>Z,>> (1, 2)
camelia (((a 1)) ((b 2)) ((c 1)))
Voldenet , is the default
Xliff ab5tract: Oh. So that's the difference. SMH
Voldenet the output is somewhat weird
Xliff Voldenet++
ab5tract m: dd <a b c> »Z,» (1,2) 23:16
camelia ((("a", 1),).Seq, (("b", 2),).Seq, (("c", 1),).Seq)
ab5tract seqs all the way down
Voldenet in fact
m: dd <a b c> »,» (1,2)
camelia (("a", 1), ("b", 2), ("c", 1))
Voldenet probably more useful without Z 23:17
ab5tract Xliff: I agree that it's LTA though. if you file a ticket, I'll try to poke at it 23:19
Xliff m 23:21
m: <a b c> »,» ( [0,0], [1,0] )
camelia Potential difficulties:
Useless use of »,» in sink context
at <tmp>:1
------> <a b c> <HERE>»,» ( [0,0], [1,0] )
Lists on either side of non-dwimmy hyperop of infix:<,> are not of the same length while recursing
left: 1 eleme…
Xliff Instead of (a [0,0]) (b [1,0]) (c [1,0]) 23:22
m: <a b c> »Z,» ( [0,0], [1,0] )
camelia Potential difficulties:
Useless use of »Z,» in sink context
at <tmp>:1
------> <a b c> <HERE>»Z,» ( [0,0], [1,0] )
Lists on either side of non-dwimmy hyperop of are not of the same length while recursing
left: 1 elements, ri…
ab5tract don't forget a dd or say 23:24
Voldenet mmm nodal magic, my greatest enemy 23:39
m: <a b c> »,» (\[0,0], \[1,0])
camelia Potential difficulties:
Useless use of »,» in sink context
at <tmp>:1
------> <a b c> <HERE>»,» (\[0,0], \[1,0])
Voldenet m: say <a b c> »,» (\[0,0], \[1,0])
camelia ((a \([0, 0])) (b \([1, 0])) (c \([0, 0])))
Voldenet yes, of course it works :/
I'm not sure how to prevent hyper from doing that 23:41
maybe… don't use hyper at all 23:46
m: say <a b c> Z (|([0,0], [1,0]) xx *)
camelia ((a [0 0]) (b [1 0]) (c [0 0]))
Voldenet m: say <a b c> Z |([0,0], [1,0]) xx * 23:48
camelia ((a [0 0]) (b [1 0]) (c [0 0]))