🦋 Welcome to the MAIN() IRC channel of the Raku Programming Language (raku.org). This channel is logged for the purpose of keeping a history about its development | evalbot usage: 'm: say 3;' or /msg camelia m: ... | Log inspection is getting closer to beta. If you're a beginner, you can also check out the #raku-beginner channel!
Set by lizmat on 25 August 2021.
leont Yeah, there are only $_, $/ and $!, and the last one is barely magical. 00:00
Xliff MasterDuke++ 00:01
MasterDuke: Getting a 404 from that URL 00:02
leont: Don't the dynamics count?
leont I wouldn't consider them magical, TBH
Xliff OK 00:03
00:06 reportable6 left
leont They're just differently namespaced 00:11
00:32 timm left 00:33 timm joined 00:37 timm left 00:43 timm joined
guifa Nemokosch: the topic actually is a bit different between Perl and Raku. The idea of the topic in perl is from pro-drop languages (Larry is a linguist by trade). In, e.g., Spanish, I can say "El perro es grande. Es negro. Ladra." (literally: The dog is big. Is black. Barks"). There's no need to repeat the subject 00:48
Each followed the natural language convention that a topic is established and continued, but Perl did it at a line-by-line level, and Raku does it a block level 00:49
Generally, you shouldn't need to reference the topics, just like in such pro-drop languages, you'd rarely use the subject explicitly except for emphasis 00:51
to me, given $foo { .bar; .baz; .abc; .say } is a bit clearer than $foo.bar; $foo.baz, $foo.abc, $foo.say 00:52
I guess with is probably the better control word there but both work
The nice thing though is, just like my students learning Spanish, you're not *required* to use it. AFAIK, every structure in Raku that might use a topic variable has a way to use an explicit named variable instead, at the cost of a bit more line noise (although, no more than most other programming languages) 00:54
Nemokosch the dynamics don't count in my opinion, even though they also seem to be a "writers first" feature 01:05
for the topic variable, I don't know how it is in Perl and I suspected it got simplified in Raku
still, I think it's useful to think "inside the box", and outside of the Perl macroverse 01:07
I'm no ambassador of outsiders but I have the impression many people would raise their eyebrows if you told them that Raku was designed with the outsider reader in mind
01:09 reportable6 joined
> to me, given $foo { .bar; .baz; .abc; .say } is a bit clearer than $foo.bar; $foo.baz, $foo.abc, $foo.say 01:09
I kind of agree, also, this kind of code is a pleasure to refactor even with notepad
01:12 xinming left 01:14 xinming joined 01:20 f00 joined, timm left 01:24 f00 left, f00 joined 01:29 f00 left 02:29 shareable6 left, greppable6 left, linkable6 left, squashable6 left, releasable6 left, evalable6 left, tellable6 left, quotable6 left, benchable6 left, coverable6 left, notable6 left, bloatable6 left, committable6 left, reportable6 left, sourceable6 left, bisectable6 left, unicodable6 left, nativecallable6 left, statisfiable6 left, committable6 joined, evalable6 joined 02:30 benchable6 joined, coverable6 joined, reportable6 joined, sourceable6 joined, quotable6 joined, squashable6 joined, linkable6 joined 02:31 unicodable6 joined 02:32 tellable6 joined 02:37 xinming left, xinming joined
guifa Nemokosch: using the topic variable definitely takes a little bit to get used to, but once you do, it's very easy on the eye as a user. At the very least, though, starting a line with a .foo should signal to a non-Raku user that *something* is going on, and hopefully it doesn't take long to find out it's acting on the topic 02:40
leont And unlike in Perl (where it's essentially a dynamic variable) it's lexical, so it doesn't have weird action at a distance issues. 02:43
03:29 releasable6 joined 03:31 statisfiable6 joined, bisectable6 joined 04:23 xinming left 04:24 xinming joined 04:30 greppable6 joined 04:32 notable6 joined 05:08 toastloop joined 05:30 bloatable6 joined 05:49 mexen joined 06:07 reportable6 left 06:18 Kaiepi left 06:21 Altai-man_ joined 06:22 Altai-man_ left 06:30 nativecallable6 joined 06:37 Kaiepi joined 06:45 Altai-man left 06:48 sena_kun joined, sena_kun left 07:09 reportable6 joined 07:19 phogg left 07:24 abraxxa joined 07:29 abraxxa left, abraxxa joined 07:31 phogg joined 07:52 jjido joined 08:06 Sgeo left 08:07 Sgeo joined, jjido left 08:30 shareable6 joined 08:34 jjido joined 08:45 jjido left 08:48 toastloop left 08:49 toastloop joined 08:51 dakkar joined 09:00 f00 joined 09:18 patrickb left 09:19 patrickb joined 09:35 jjido joined 09:41 Darkcoal joined, Sgeo left 09:50 toastloop left
Voldenet I consider dynamic variables mostly an antipattern 10:02
the biggest issue with them is when you need to use some process using changing dynamic variable 10:03
10:05 jjido left
Voldenet `my $*unclear = "a"; code(); { my $*unclear="b"; code(); }; code()` vs `code("a"); code("b"); code("a");` 10:06
Nemokosch they are essentially hidden globals
again, okay for prototyping
Voldenet I'd say okay for rarely used code that never needs to switch context, like loggers 10:07
10:08 f00 left
Nemokosch what would that look like? 10:10
Voldenet for instance: `my $*sql-executing = -> $_ { .query.say }; some-complicated-process-using-sql($conn.start-transaction)` 10:11
however, `$conn.sql-executing = …` would be as fine 10:12
but then it would pollute connection's state, so it would start logging things outside of the current routine 10:13
Nemokosch tbh it's hard to come up with a good use 10:14
one thing is sure: it's never unavoidable 10:16
lizmat please note that dynamic variables are used extensively internally, without it e.g. react / whenever would not work 10:33
(or at least be a lot harder to implement)
Voldenet While there are good examples where it makes sense, "avoid it until you decide that you can't" is a good rule 10:38
Nemokosch I'm sure there are good examples, I've just never come across them so far 😛 10:39
lizmat dynamic variables make excellent default values for parameters 10:45
take e.g. the $*SCHEDULER variable. If you want to use another scheduler for your code, you don't need to pass it along everywhere, you just need to specify it in the outer dynamic scope of your code 10:46
El_Che (who schedules the scheduler?) 10:49
lizmat the core does :-)
El_Che and who cores the core? :) 10:50
(weirdly enough, it's a verb)
lizmat I don't think I can verb my way out of this :-) 10:51
El_Che :)
Nemokosch 😂 10:52
El_Che Star Trek famously ejects the core more often than not
Efforts to speed up the raku core should be under the Scotty umbrella 10:53
Voldenet scheduler can schedule the scheduler just fine 10:56
El_Che and decides it's fine? 10:59
Voldenet "fine" is a decision made based on sanity of the original author 11:01
m: my $*SCHEDULER = class :: { method cue($code) { my $*SCHEDULER = CurrentThreadScheduler.new; start $code(); } }.new; await start { "why though".say };
camelia why though
Nemokosch :DD 11:02
El_Che Voldenet: so we end up with the "Lary is always right" axioma :) 11:06
Voldenet I've seen threading apis using schedulers as method arguments and… uh, end result was difficult to understand 11:08
El_Che I imagine 11:11
"Imagine there is no scheduleeeeeer" 11:12
Voldenet Scheduler is an implementation detail
lizmat the default scheduler is an implementation detail, yes
but you can write your own, if you want to
Voldenet so it's useful to keep it hidden from people
lizmat well, most people don't know of its existence, so I think that part worked out :-) 11:13
El_Che lizmat: I see you play the long game :) 11:16
lizmat well, if you can't tell that by now... :-)
El_Che sue me, write me a open letter :P 11:17
(I need to drink less coffee monday morning :) )
c.tenor.com/E-pWfHWt2xUAAAAd/tweak...-tweak.gif 11:21
11:24 evalable6 left, linkable6 left, evalable6 joined 11:25 linkable6 joined 11:26 jjido joined
Voldenet If you think you've had too much coffee, you need more of it 11:26
El_Che Voldenet: it sounds like a hangover fix 11:32
11:55 jjido left 11:57 frost left 12:00 jjido joined 12:07 reportable6 left
qorg11 Any way to convert bytes to base32? 12:11
12:23 jjido left 12:25 frost joined
lizmat m: dd 42.base(32) 12:27
camelia "1A"
lizmat qorg11 ^^
qorg11 Is that the encoding? 12:34
Like base64 but base32?
lizmat m: dd 65.base(32) 12:35
camelia "21"
lizmat m: dd 63.base(32)
camelia "1V"
Voldenet it's not rfc4648 base32 12:36
CIAvash qorg11: didn't find anything in the ecosystem for base32, but maybe this will help: github.com/ugexe/Perl6-Base64/blob...Base64.pm6
Voldenet it's base32 hex
lizmat there's also raku.land/zef:raku-community-modul...ME::Base64 12:37
12:57 jjido joined 13:08 hankache joined 13:17 hankache left 13:37 euandreh left 14:00 frost left
lizmat And yet another Rakudo Weekly News hits the Net: rakudoweekly.blog/2022/02/21/2022-...rly-co-op/ 14:02
14:06 jjido left 14:08 reportable6 joined 14:12 euandreh joined 14:39 euandreh left 14:41 euandreh joined 14:45 qorg11 left, qorg11 joined 14:46 qorg11 left, gotem joined 14:55 euandreh left 15:02 dakkar left 15:03 dakkar joined 15:09 curiosa joined 15:10 curiosa joined 15:14 silug left, silug joined
Nemokosch um, the second example of the second task is faulty again... where would you report? 15:25
talking about the weekly challenge
Geth ecosystem: c11ebef951 | (Elizabeth Mattijsen)++ | META.list
Remove Color, Web::App and Web::App::MVC
15:49 euandreh joined
[Coke] reads the weekly #153, and is not surprised that factorions seem a little scarce. 15:58
Geth ecosystem: e62f923cf6 | (Elizabeth Mattijsen)++ | META.list
Move Andrew Egeler's modules to raku-community-modules

Well, for those that now live in the Raku Community Modules Adoption Center.
guifa Nemokosch: I definitely agree that dynamics are something to be used sparingly. But they are really useful when you hit those cases. One semi-useful place has been where I have a large number of small subs that need to be passed mostly the same variables, but I'm too lazy to write it out 16:09
my %formatters = a => { $*day }, b => { $*month }, c => { $*date-delimiter } 16:10
lizmat guifa: you could also let those subs share a lexical scope :-) 16:11
guifa I mean, yes, assuming that works in the code structure
16:11 patrickb left
guifa then you can just set those, and do something like $fmt-string.comb.map({ %formatters{$_}() }).join et violà 16:12
Geth ecosystem: 9d0c359b7d | (Elizabeth Mattijsen)++ | META.list
Freeze Net::SMTP

While we're moving it to the zef ecosystem
16:12 patrickb joined
guifa lizmat hence I said "semi-useful". Given that the code for formatters for the international datetime formatting is severla hundred lines long, it makes sense to pull it to a different scope (module, even, I think is how I last left it, but that module is ripe for a massive rewrite with RAST) 16:13
lizmat :-)
guifa ended up using $^vars though
turns out those are the fastest way to pass args into a block
at least as of last year when I benchmarked it 16:14
lizmat ah? faster than an explicit signature ?
guifa indeed! It was quite surprising to me
lizmat I thought they codegenned to the same thing?
guifa in RAST at least, they have separate nodes, but maybe at the QAST level they are handled the same 16:15
lizmat well, I'm not seeing any difference between: 16:16
my $a = { $^a + $^b }; $a(42,666) for ^10000000
my $a = -> $a, $b { $a + $b }; $a(42,666) for ^10000000
guifa Almost certainly newdisp touched on some of that stuff, yeah?
lizmat wouldn't think so 16:17
what it touched is how the infix:<+> is dispatched
guifa hmm, I dunno then 16:18
my benchmark is even older than last year
lizmat m: my $a = -> $a, $b { $a + $b }; dd $a.signature
camelia :($a, $b)
guifa "As of Dec 2020 in Rakudo, implicit positionals are the fastest"
lizmat m: my $a = { $^a + $^b }; dd $a.signature
camelia :($a, $b)
lizmat ok, not sure what changed since then 16:19
guifa I'd almost do a new benchmark now with my code except … that's a lot of refactoring to do to test with when I'm just gonna gut it all ;-) 16:20
lizmat yeah, sure. no pb :-)
I think there *is* a difference between handling of \a and $a in a signature nowadays
if it can be proven that $a is *not* an Iterable at compile time 16:21
16:21 silug left
guifa oh yeah, this also reminds me I need to start working on DateTime::Calendars 16:23
guifa stares forbodingly at the book on his shelf titled Calendrical Calculations and the insane amounts of math and astronomical calculations and stuff
lizmat :-) 16:24
guifa I guess an initial test could be one of the ones that's identical to gregorian, but for the epoch. I'm just curious if there's a way I can somehow get ::Calendars and ::Timezones to play nicely, such that they can be called in either order, and/or independently, deep in module scope or at top level scope 16:26
16:26 silug joined
guifa I *think* it would be easier if CORE::DateTime had a .calendar, .era, .cycle, .quarter attributes (easily supplied with initial attributes of 'gregorian', {.year > 0}, 0, { (.month + 2) % 3 }, but I think that'll be a summer project for me to figure out all that 16:32
lizmat I think to have that in core, would be troublesome performance wise for the cases that don't need it :-(
Anton Antonov I have a regex that parses code lines, for example, ``` 16:33
my regex CodeLine {
$<indent>=(\h ** 2)
$<code>=(<-[\h]> [<alpha> | '(' | ')' | '_' | '.' | \s | '::' | '$']+ )
I want to be able to use a variable to specify the number of indentation spaces (it is hard coded as 2 above.) Can specify that as an argument for the regex above, or should I make a function that creates regexes using a quantifier as an argument?
guifa my regex CodeLine($indent) { … \h ** $indent … } 16:35
err 16:36
that $indent needs to go into a code block 16:39
\h ** {$indent}
Although it looks like passing that variable to the regex is annoying outside of grammars… so maybe use .....
guifa pauses while scrolling up and looking at Nemokosch quietly ;-) 16:40
dynamic variable :D
Anton Antonov @guifa Thanks! 16:41
guifa m: my regex foo { \h ** {$*indent} }; my $*indent = 2; say ' ' ~~ &foo; say ' ' ~~ &foo; 16:42
camelia Nil
「 」
Anton Antonov @guifa Yes, I tried that you suggest in the last line first without the curly brackets around `$indent` , so, yes, that works. 16:43
16:58 patrickb left 17:00 vrurg left 17:01 vrurg joined 17:04 patrickb joined 17:07 ccntrq joined
Geth ecosystem: 22ec24e8b2 | (Elizabeth Mattijsen)++ | META.list
Freeze Email::Simple

While we're moving it to the zef ecosystem
17:13 abraxxa left 17:21 mexen left 17:26 Sgeo joined 17:29 silug left, djerius left 17:31 djerius joined 17:32 silug joined 17:34 dakkar left 17:41 silug left 17:48 silug joined 17:51 vrurg left 18:07 reportable6 left, curiosa left 18:19 MasterDuke left
Geth ecosystem: 9d0d47bc59 | (Elizabeth Mattijsen)++ | META.list
Freeze Net::IMAP

While we move it to the zef ecosystem
19:21 vrurg joined 19:36 ccntrq left 19:59 MasterDuke joined 20:10 reportable6 joined 20:20 Darkcoal left 21:03 curiosa joined
curiosa Hi, I have a question. Let's say that you you have an object with many ro attributes. You want a method that return a new object with everything identical to the caller a part a few attributes. What would be the best way to write such a method in Raku? 21:05
one option is clearly to invoke new with all the arguments taken from the caller a part the few that are changed; this is quite bloated 21:06
another option is to make all attributes rw and then call copy and modify only what need to modify, this doesn't fell the Raku's way
what would you do?
21:15 discord-raku-bot left, discord-raku-bot joined
Xliff curiosa: Why would you want to do things that way? 21:19
If you want to selectively allow attributes to be rw, create methods for each attribute that allow you to customize the logic. 21:20
tonyo m: class AA { has $!o; has $!p; submethod BUILD(:$!o = 1, :$!p = 2) { }; method COPY(:$o = $!o, :$p = $!p) { return AA.new(:$o, :$p); }; method o {$!o}; method p{$!p}; }; my $a1 = AA.new(:o(2), :p(3)); my $a2 = $a1.COPY(:p(6)); dd [$a1.o, $a1.p]; dd [$a2.o, $a2.p]; 21:24
camelia [2, 3]
[2, 6]
Xliff m: class A { has $!may-not-be-writeable; has %!attribute-writeable; method may-not-be-writeable is rw { Proxy.new( FETCH => $!may-not-be-writeable, STORE => -> $, \v { unless %!attribute-writeable{ &*ROUTINE.name } { say "Attribute is not currently writeable!' return }; $!may-not-be-writeable = v }; }; method set-rw { %!attribute-writeable{ '$!may-not-be-writeable' } = True; }; method set-ro { %!attribute-writeable{ 21:26
'$!may-not-be-writeable' } = False }; };
camelia ===SORRY!=== Error while compiling <tmp>
Unable to parse expression in subscript; couldn't find final '}' (corresponding starter was at line 1)
at <tmp>:1
------> ; method set-ro { %!attribute-writeable{⏏<EOL>
expecting any …
Xliff Hmm... I will have to repl this. One sec.
tonyo curiosa: ^ that pattern will let you control what can be modified on copy 21:27
curiosa I prefer to do things in the most simple way 21:41
the thing is that I have 21:42
a language that i am parsing that specify types 21:43
and for each type there is an attribute that is number-of-bytes, let's say
then I have arrays 21:44
and arrays should multiply that attribute by the number-of-elements
and return also a type 21:45
all this is happening in the actions of a grammar, such that array-of gets the type of the element as a made argument 21:46
tonyo you can use some introspection to get that done in actions if you don't know what the attributes are at compile time, 21:47
Xliff replit.com/@Xliff/YellowgreenAdole...#main.raku 21:52
^^ curiosa
curiosa that's nice 21:57
tonyo m: class A {has $!o = 6; method o { $!o }; }; my $a1= A.new; sub copy($of, %vals) { my $cp = $of.WHAT.new; for $cp.^attributes.grep(*.readonly) -> $attr { $attr.set_value($cp, (%vals{$attr.name} // $attr.get_value) );}; $cp }; dd [$a1.o, copy($a1, '$!o' => 12).o] 22:00
camelia [6, 12]
tonyo generic way to do it if you don't know what the object is at compilation ^ 22:01
22:04 slowtype- joined 22:05 slowtyper left 22:11 vrurg left 22:12 vrurg joined 22:19 vrurg left, vrurg joined 22:27 Altai-man joined 22:35 Altai-man left
japhb Why not .clone? 22:42
curiosa omg, clone is perfect! 22:43
does clone calls TWEAK ? 22:46
22:49 lgtaube left
curiosa damn, it doesn't 22:51
m: class a { has $.beer = 1; submethod TWEAK(:$beer) { $!beer = 2 * $!beer; }  }; my $b = a.new(:beer(3)); say $b; say $b.clone: :beer(4)
camelia a.new(beer => 6)
a.new(beer => 4)
curiosa isn't this a bug?
japhb Kinda feels like it, yeah. File a Rakudo issue? 22:56
23:03 lgtaube joined
tonyo .clone doesn't let you control what gets copied 23:30
23:33 curiosa left 23:40 ocomport joined
gfldex PWC#153 spoiler warning: gfldex.wordpress.com/2022/02/22/lo...ly-simply/ 23:41
ugexe if TWEAK was rerun on .clone the it could modify various internal state which isn't what .clone should do 23:59