🦋 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
leont They're just differently namespaced 00:11
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
> 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
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
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
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
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
an
(I need to drink less coffee monday morning :) )
c.tenor.com/E-pWfHWt2xUAAAAd/tweak...-tweak.gif 11:21
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
qorg11 Any way to convert bytes to base32? 12:11
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
lizmat And yet another Rakudo Weekly News hits the Net: rakudoweekly.blog/2022/02/21/2022-...rly-co-op/ 14:02
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:44
[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.
16:08
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
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
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 :-)
ok
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
and
my $a = -> $a, $b { $a + $b }; $a(42,666) for ^10000000
now
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
oh
jeez
my benchmark is even older than last year
github.com/alabamenhu/IntlFormatDa...atters.pm6
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
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
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
Geth ecosystem: 22ec24e8b2 | (Elizabeth Mattijsen)++ | META.list
Freeze Email::Simple

While we're moving it to the zef ecosystem
17:08
Geth ecosystem: 9d0d47bc59 | (Elizabeth Mattijsen)++ | META.list
Freeze Net::IMAP

While we move it to the zef ecosystem
18:23
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?
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
japhb Why not .clone? 22:42
docs.raku.org/routine/clone
curiosa omg, clone is perfect! 22:43
does clone calls TWEAK ? 22:46
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
tonyo .clone doesn't let you control what gets copied 23:30
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