🦋 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.
rf Evening folks 01:19
grondilu Hi all 08:36
I was about to rewrite rosettacode.org/wiki/Pernicious_numbers#Raku to use a subset, then I realized there is no subset for primes anyway so it doesn't make much sense to create one for an even more niche subset 08:37
lizmat subset prime of Int where *.is-prime 08:38
?
grondilu so why don't we have a `Prime` subset for primes instead of &is-prime?
lizmat because you can create one like ^^ ?
grondilu but I'm too lazy for that. Why not put it in the core? 08:39
lizmat well, it's the perennial discussion, really 08:41
lizmat why isn't raku.land/zef:lizmat/Slang::Subscripts in core ? 08:41
grondilu well what we put in the core or not is kind of arbitrary. Is TimToady still around to decide of these stuff? 08:42
lizmat no, jnthn is de facto pumpkin. and then we have the RSC that sometimes decides things :-) 08:43
a PR is a good place to start a discussion 08:44
see e.g. adding the "is-monotonically-increasing" addition to iterators I PRed yesterday
github.com/rakudo/rakudo/pull/5243 08:45
grondilu noted 08:45
Nemokosch I don't like this idea, to be frank. It hides complexity for very little visual gain. 08:47
and it's a very slippery path to walk down upon overall. By the same chance, one might create an Odd subset, an Even subset, a SquareNumber subset, a PerfectNumber subset and the list goes on for eternity. 08:51
grondilu not for eternity. 08:54
grondilu besides, we've already decided to add a &is-prime function in the core. This is a spot in the core namespace. The question is : why should this spot be put in the function namespace and not in the subset namespace? 08:56
grondilu by comparison, we do not have a &is-odd or &is-even functions. 08:57
Nemokosch because you can always just write that with literally less characters: %%2 09:00
I think it's "generous" that there is a prime test maintained as core but again, I don't find it fortunate to hide a prime test behind something that looks like an actual type of things 09:01
grondilu why? 09:02
I don't see anything wrong with that.
Nemokosch because it's not an actual type, it's code that runs on each occasion
if you don't, you are free to define it for yourself
grondilu 🤔
grondilu I see your point. A subset runs some code everytime, I forgot that. 09:03
Nemokosch subsets are best used as a domain specific thing overall. When somebody just looks at an apparent type name, they might not be aware (or conscious about it) that they are actually running code every time they add the constraint and assign a value to a constrained variable 09:04
grondilu is convinced 09:06
Nemokosch m: Subset Prime is Int
Raku eval Exit code: 1 ===SORRY!=== Error while compiling /home/glot/main.raku Undeclared names: Prime used at line 1 Subset used at line 1 Undeclared routine: is used at line 1
Nemokosch that's not quite what happened in the REPL 09:07
m: Subset Prime is Int where *.is-prime
Raku eval Exit code: 1 ===SORRY!=== Error while compiling /home/glot/main.raku Two terms in a row at /home/glot/main.raku:1 ------> Subset Prime is Int⏏ where *.is-prime expecting any of: infix infix stopper postfix statement end statement modifier statement modifier loop
Nemokosch yep, this one
should have known better than uppercase "subset" but the error is wrong for sure
lizmat I'd say LTA 09:08
Nemokosch I think this is closer to downright false than just obscure 09:09
is there a way to see how it was parsed? 09:09
lizmat m: Foo Bar Baz 09:10
camelia ===SORRY!=== Error while compiling <tmp>
Undeclared names:
Bar used at line 1. Did you mean 'Bag'?
Baz used at line 1. Did you mean 'Bag'?
Foo used at line 1
lizmat m: Foo Bar is Baz
camelia ===SORRY!=== Error while compiling <tmp>
Undeclared names:
Bar used at line 1. Did you mean 'Bag'?
Baz used at line 1. Did you mean 'Bag'?
Foo used at line 1
Undeclared routine:
is used at line 1
lizmat m: Foo Bar is Int
camelia ===SORRY!=== Error while compiling <tmp>
Undeclared names:
Bar used at line 1. Did you mean 'Bag'?
Foo used at line 1
Undeclared routine:
is used at line 1
lizmat m: Foo Prime is Int 09:11
camelia ===SORRY!=== Error while compiling <tmp>
Undeclared names:
Foo used at line 1
Prime used at line 1
Undeclared routine:
is used at line 1
lizmat aah... Subset is a class
m: dd Subset.HOW.name
camelia ===SORRY!=== Error while compiling <tmp>
Undeclared name:
Subset used at line 1
lizmat m: dd Subset
camelia ===SORRY!=== Error while compiling <tmp>
Undeclared name:
Subset used at line 1
lizmat no?
m: Foo Prime is Int where *.is-prime 09:12
camelia ===SORRY!=== Error while compiling <tmp>
Two terms in a row
at <tmp>:1
------> Foo Prime is Int⏏ where *.is-prime
expecting any of:
infix
infix stopper
postfix
statement end
Nemokosch somehow the where clause interfered
lizmat yeah, before that, it could be interpreted as
Nemokosch maybe it's some sort of variable declaration
but what sort 😆 09:13
lizmat m: Foo(Prime(is(Int)))
camelia ===SORRY!=== Error while compiling <tmp>
Undeclared names:
Foo used at line 1
Prime used at line 1
Undeclared routine:
is used at line 1
Nemokosch anyway, for now, I'll just take a note; that's not what I wanted to test clearly 09:16
m: subset Prime of Int where { say 'BOOM'; .is-prime }; my Prime $ensured = 97; my Prime $new = $ensured; 09:18
Raku eval BOOM BOOM
Nemokosch I don't know if the second "BOOM" has a theoretic reason or if it's desirable but one thing is sure
as things stand, subsets are very expensive 09:19
lizmat I guess the second BOOM could be optimized away with an nqp::eqaddr check 10:03
Geth App-Rakubrew: 335f5eee4b | (Patrick Böker)++ | 3 files
Version 36
10:21
patrickb [Coke], ugexe, vrurg, whoever else uses Rakubrew on ARM MacOS: The latest update (version 36) will break your installation. You need to manually do the update by downloading rakubrew.org/macos_arm/rakubrew manually and replacing ~/.rakubrew/bin/rakubrew with it. (The update process will warn and instruct you as well.) 10:41
Nemokosch what changed in the new version? 10:46
Anton Antonov @patrickb Good to know! 10:49
... and who did it !?
Nemokosch by the way, there is something tricky... something "iterable" in Raku is not necessarily Iterable 10:50
m: 'asdgg'.encode('iso-8859-1') ~~ Iterable 10:51
Raku eval
Nemokosch oops
m: 'asdgg'.encode('iso-8859-1') ~~ Iterable andthen .say
Raku eval False
Nemokosch however, does it really make sense to say that it's not "iterable"?
m: .say for 'asdgg'.encode('iso-8859-1');
Raku eval 97 115 100 103 103
Nemokosch in Raku, everything might be "iterable" and Blobs clearly have meaningful semantics when iterated 10:52
patrickb Nemokosch: v36 only contains the fix for updating ARM MacOS. But since the code for the update process is run in the installed version and not in the new version one needs to do this one update manually. 11:04
tellable6 patrickb, I'll pass your message to Nemokosch
patrickb Anton Antonov: What do you mean by "who did it !?" 11:05
Anton Antonov @patrickb It is just a joke. (Or an attempt for one...) 11:39
That said, in the past I spent disproportionate amount of time figuring out installation problems with Raku on macOS with M1 processor. (Both packages and raku and rakubrew.) 11:41
Voldenet Nemokosch: in fact I wonder why Positional role isn't iterable, which is a lot wider than Blob (and is supported by Blob) 11:54
tellable6 Voldenet, I'll pass your message to Nemokosch
Voldenet it appears that simply adding `does Iterable` on Blob role would fix things 11:55
Nemokosch I don't know but Blob is "iterable" for practical purposes because it implements the list method 11:57
Anything that implements that method is "iterable" for practical purposes 11:58
Voldenet But it still is valid to mark that as iterable, making a copy is simply implementation detail in that case 11:59
not necessary, but not invalid either
Nemokosch agreed 12:00
it shouldn't matter why/how it is iterable, the "iterability" is in the fact that it has meaningful semantics for obtaining an iterator 12:01
and this leads to funny things like, it works with for˙or map even, but lazy is a lookup error 12:02
because a lot of stuff comes straight from Any, using the list method 12:03
Voldenet there's something magical about "Any" implementing things that are supposed to be specific to iterable things 12:04
Voldenet m: say "???".map(* x *) 12:05
camelia Too few positionals passed; expected 2 arguments but got 1
in block <unit> at <tmp> line 1
Voldenet m: say "???".map({ $_ x $_ }) 12:06
camelia Cannot convert string to number: base-10 number must begin with valid digits or '.' in '⏏???' (indicated by ⏏)
in block <unit> at <tmp> line 1
Voldenet m: say "???".map({ $_ ~ $_ })
camelia (??????)
Voldenet m: .say for Nil 12:09
camelia Nil
Voldenet I'd argue that in this case (and .map) it'd be more useful to treat Nil as empty, so $whatever.map(*.thing) becomes () 12:10
lizmat Nil indicates the absence of a value where there is supposed to be one 12:11
Voldenet So, optional with no value 12:12
lizmat nope, there was supposed to be a value, but there wasn;t
think of it as a box that is supposed to have something in it, but a box must be there
you want to take away the box :-) 12:13
Voldenet I see a nail and I'd like to apply monad hammer to it
lizmat well, that's Empty 12:14
generating Empty is really easy in the context of a Map
*map
m: say (1..10).map({ $_ unless $_ == 5})
camelia (1 2 3 4 6 7 8 9 10)
Voldenet Oh, that's clever, so instead of some item a Empty slip can be used in `for/map` context 12:17
s/a /an /
lizmat yup 12:18
m: dd do if 0 { }
camelia Empty
lizmat a failed conditional returns Empty 12:19
Voldenet in fact the only pain I have with Any.map is `my $x = (1, 2, 3); .say for $x;` 12:21
lizmat but that's because it's itemized in the variable 12:22
m: my $x := (1, 2, 3); .say for $x # unitemized
camelia 1
2
3
Voldenet Yes, and that's sort of what I'd expect from perl 12:23
m: y $x = (1, 2, 3); .say for @$x;
camelia ===SORRY!=== Error while compiling <tmp>
Unsupported use of y///. In Raku please use: tr///.
at <tmp>:1
------> y⏏ $x = (1, 2, 3); .say for @$x;
Voldenet m: my $x = (1, 2, 3); .say for @$x;
camelia 1
2
3
Voldenet well, maybe I shouldn't kick .map too hard because in either case it'd work
m: my $x = (1, 2, 3); .say for $x.map({ $_ });
camelia 1
2
3
lizmat yeah, one could argue that that shouldn't iterate either 12:28
but changing that now would have rather big consequences
Voldenet changing it the other way around (don't allow iterating on single value) would probably be safer 12:32
but probably useful enough to justify it
s/useful/not useful/
Nemokosch meh, please don't try to justify Nil wrapping into a one-element list 12:35
It probably bit me more times than anybody ever found it useful
Voldenet I'm not going to lie, Nil scares me
Nemokosch I'm not sure where I said this but I mean it seriously 12:36
Voldenet it's like 'dynamic' in C#, it's a useful part of the language, but it's scary
Nemokosch if anybody wanted to make fun of Raku, there is a painfully obvious way
"how do you mark a missing value"
and all of a sudden, you have Empty, Nil, all the type objects, and any combination of them 12:37
even Failure to some extent
Voldenet Empty is obviously a monad, Type objects are nulls, I don't know how to explain Nil 12:38
Nemokosch Empty which is .DEFINITE but not .defined
// checks for .defined, 😄 checks for .DEFINITE 12:39
thank you discord...
lizmat m: my $a is default(42); say $a; $a = 666; say $a; $a = Nil; say $a
camelia 42
666
42
lizmat m: my $a is default(42); say $a; $a = 666; say $a; $a = Empty; say $a
camelia 42
666
()
Voldenet m: my @o is default(0) = ^5; @o[3] = Nil; say @o
camelia [0 1 2 0 4]
Nemokosch m: my @p = Nil; dd @p 12:40
Raku eval Array @p = [Any]
Voldenet It's all obvious, default value is Any by default
Nemokosch there should be a level of WAT that shouldn't be allowed, no?
Voldenet to be honest
Nemokosch a level of WAT where an explanation isn't sufficient anymore
no matter how many turns I take, I always arrive to a rather general statement 12:41
Voldenet m: my \default-o := 0; my @o = ^5; @o[3] = default-o; say @o
camelia [0 1 2 0 4]
Voldenet it's pretty similar to the above but obvious to people not knowing the language well 12:42
Nemokosch either @vars get a proper identity, or they are second-hand citizens not worth being called a variable, and hence to be disadvised to newcomers
Voldenet oh and 12:43
m: my @o is default(0) = ^5; @o[3] := Nil; say @o
camelia [0 1 2 Nil 4]
Nemokosch they are Java reference objects that kinda sorta pretend to be C-style actual data objects 12:44
I have been thinking about this whole containerisation story a lot, still not sure about the solution 12:48
Voldenet as a related thing - it that feels a bit weird that anything can become @x-sigiled variable
m: my @x is Compiler; @x[2] = 42
camelia Index out of range. Is: 2, should be in 0..0
in block <unit> at <tmp> line 1
Voldenet I'd expect it to require Positional role at least 12:49
Nemokosch m: my @x is Compiler; @x.WHAT.say;
Raku eval (Compiler)
Nemokosch pfff
I thought this was forbidden 12:50
Voldenet You can bind anything to it
m: my @x is Hash; @x{"hello"} = "world"; say @x
camelia {hello => world}
Nemokosch is this not simply a bug? 12:51
one problem with containers is that the term itself is not clearly defined. If we think of a container as something that can STORE values, clearly there are different kinds of containers, just as there are different kinds of assignments. However, the number of indirections is not the same for these containers 12:54
Voldenet Not a bug, more like using tools wrong
Nemokosch the only "containerizer" is Scalar. Now the next problem is that containerisation and itemisation is tied together 12:55
Voldenet m: my @x is Hash; @x{"a"} = "b"; @x{"b"} = "c"; say @x[0]
camelia {a => b, b => c}
lizmat there's also Proxy
afk&
Nemokosch wanting to have an identity for assignment is perfectly legit but that use case rarely ever has anything to do with how you want the data to be traversed in a for loop 12:56
Voldenet You could say that @x and %x are pointless when using perl5 12:57
Nemokosch a for loop on a nested Array will always trip a newcomer up, it has happened on numerous occasions, I'd say most people will be struck by that at first 12:58
regardless, you might want to swap/reassign an Array sometimes, and in those cases, you are forced to carry around a container just to do that 12:59
m: my @choices = <a b c>; given @choices { $_ = <d e f>; } 13:00
Raku eval Exit code: 1 Cannot assign to an immutable value in block <unit> at main.raku line 1
Nemokosch right, "immutable value" 13:00
Voldenet In fact, if someone wanted some advice on writing perl/raku, $-sigiled variables almost everywhere are the way to go 13:01
Nemokosch exactly...
that's "what you want"
Voldenet But % and @ are extremely useful in tons of cases
Nemokosch could you show one such a case? 13:02
Voldenet especially if your @ is Positional and % is Associative
Nemokosch Btw I'd also proceed to say that Array over List and Hash over Map is similarly "what you want"
not because of the mutability (the latter types can also carry containers, mind you) but because of the metadata that you get with all items when they have containers 13:03
Voldenet > ls | raku -ne 'state @x; @x.push($_); END say @x' 13:04
…aaand using $x would also work :/ 13:05
Nemokosch I think if someone wanted to estimate the pros and cons, benefits and risks of choosing $var vs @var, they would really not be equal choices 13:06
yet they are presented as if they were
and no, this isn't about particular types of data
this is about "variable-y" behavior 13:07
Voldenet I'm used to this only because in perl5 `push($x, $_)` is invalid
so you sort of get into using % and @ in most scopes where you don't want to transfer any references… 13:08
Nemokosch containers are useful - the lack of containers, by contrast, is not nearly as useful
Voldenet and if you do, you put it into a scalar assp
Nemokosch and what @vars and %vars offer is not another thing, just a lack
the metaphysical aspect of this is interesting nevertheless 13:10
Voldenet Any became too flexible for its own good
m: my $x; $x{"a"} = 42; say $x
camelia {a => 42}
Voldenet m: my $x; $x[1] = 42; say $x 13:11
camelia [(Any) 42]
Voldenet so far so good
m: my $x; $x[1] = 42; $x{"a"} = 42; say $x
camelia Type Array does not support associative indexing.
in block <unit> at <tmp> line 1
Voldenet m: my $x; $x{"a"} = 42; $x[1] = 42; say $x
camelia Index out of range. Is: 1, should be in 0..0
in block <unit> at <tmp> line 1
Nemokosch like, what state of mind did one need to say that the thing that we all knew as "variable" in virtually all languages, is just one particular category of variables, called Scalar?
now if they had the same enlightening vision about non-Scalar things, that would be out of this world 13:12
but sadly, non-Scalar things simply became this lack. They are not Scalars, nor something else.
Voldenet m: my @x; @x = 1, 2, 3; say @x 13:13
camelia [1 2 3]
Voldenet m: my $x; $x = 1, 2, 3; say $x 13:13
camelia WARNINGS for <tmp>:
1
Useless use of constant integer 3 in sink context (lines 1, 1)
Useless use of constant integer 2 in sink context (lines 1, 1)
Voldenet it's something ¯\_(ツ)_/¯ 13:14
and the first one is obviously in wantarray context
:>
Nemokosch that's just syntax 13:15
now, is extra syntax justified if you cannot put the semantics behind?
Voldenet imo it is if you justify that it represents a type of data for legibility 13:17
m: my \x = 1, 2, 3; say x # extra syntax can be used in other ways though
camelia (1 2 3)
Nemokosch legibility shouldn't have the sort of paycheck that it has for @ and % 13:21
it's bizarre that you lose the whole bind-and-assign mechanism
you lose most mutability related traits, too 13:22
Voldenet C# is even weirder
Nemokosch you lose the possibility to have a default for the whole variable
Voldenet struct and class are stored in entirely different way, but there's no different sigils or anything
it's simply _a variable_
Nemokosch so is an integer and a floating point number different 13:23
Voldenet in terms of bytes storage and operations invoked, but not in terms of variable access 13:24
Nemokosch what does "variable access" mean here?
Voldenet double x = 3.14; int y = 4; Write(x + 5); Write(y + 6);
same code, you literally see no complexity happening underneath 13:25
Nemokosch yep
happens all the time
Voldenet It's even the case with class/struct x { public int y; public int z; }
Nemokosch somewhere along the lines, this is a goal of abstractions
Voldenet Is it a problem? Yes it is
Nemokosch not necessarily 13:26
Voldenet > void DoThing(X something) { something.A = 42; }
to know whether something was mutated you need to look at definition of X
it can get trickier when you nest and mix both
Nemokosch what would happen instead of mutation? 13:27
Voldenet Absolutely nothing! :D
Nemokosch why though
I mean... who in the right mind thought that was sane behavior for any purpose
Voldenet in case of struct, DoThing gets fields from struct x pushed onto the stack as args
Nemokosch oh okay, so that's what you meant 13:28
Voldenet and if you return a struct, return fields get pushed onto the stack
Nemokosch whether it's copied or not
yeah tbh this is C++ misinterpreted
back to the sigils... 13:30
I think it's very telling that nobody ever "advertised" sigils with the container stuff that it influences so crucially
Voldenet if you tied @-variables to the stack, the difference would be enormously obvious
Nemokosch even though one cannot just say that "it's buggy, let's stay silent about it"
that's how it is designed and it would be really hard to change it, it's an integral part of how all this works 13:31
why does nobody feel that it's important - actually the most important thing - to tell people that sigils influence how assignment and mutation-related traits work? 13:32
this IS the important thing, not Positional and Associative
and this is when I strongly suspect that other people either also don't feel confident in their knowledge about this, or they just think this is too much for a beginner to take 13:33
but then it's really hard to tell them what's so good about sigils...
Voldenet Perhaps some scraps of explanatory code where you can't trivially replace @ with $ would be nice 13:35
Nemokosch It's quite possible that you know this already but still, I wanted to "process" the "Any became too flexible ..." snippets 13:37
m: my $x; $x{"a"} = 42; say $x
Raku eval {a => 42}
Nemokosch auto-vivification; if it has the default value, it can create a container out of thin air 13:38
m: my $x; $x[1] = 42; say $x
Raku eval [(Any) 42]
Nemokosch same thing, with the slight difference that "Any"thing can be indexed with [] by default anyway 13:39
(in order to make them act like one-element lists, I guess)
m: my $x; $x[1] = 42; $x{"a"} = 42; say $x
Raku eval Exit code: 1 Type Array does not support associative indexing. in block <unit> at main.raku line 1
Nemokosch can't be auto-vivified when it already has content
m: my $x; $x{"a"} = 42; $x[1] = 42; say $x 13:40
Raku eval Exit code: 1 Index out of range. Is: 1, should be in 0..0 in block <unit> at main.raku line 1
Nemokosch and this is where you can see that [] indexing "always" works so the error is different here
Voldenet btw 13:41
m: my %x is Array; %x[1] = 42; say %x
camelia [(Any) 42]
Voldenet m: my %x is Array; %x = 1, 2, 3; say %x 13:42
camelia [1 2 3]
Nemokosch what if we omit the Array part?
m: my %x; %x[1] = 42; say %x
Raku eval Exit code: 1 Index out of range. Is: 1, should be in 0..0 in block <unit> at main.raku line 1
Voldenet Of course, it's a Hash
Nemokosch cannot auto-vivify
and if we do the same with [0], it will say that the rhs has odd number of elements? 13:43
m: my %x; %x[0] = 42; say %x
Raku eval Exit code: 1 Odd number of elements found where hash initializer expected: Only saw: 42 in block <unit> at main.raku line 1
Nemokosch excellent 😄
Voldenet it's a bit more useful when you try to do multivalued hash with it, but the sigil's usage is only useful in case of default hash 13:45
`my $x = SomeHashType.new;` would be equally as good and probably more obvious 13:47
Nemokosch only the containerisation/itemisation makes some difference 13:48
but .map, for example, doesn't care from what I know
Voldenet > docs.raku.org/language/variables.h...@_variable 13:49
Nemokosch even the assignment is such a little overhead
Voldenet if you replace the @ with $, the example would still work
docs could use some example that wouldn't work otherwise, hm 13:50
Nemokosch probably that's because of the auto-vivification again
but there I can take it that @ might be more readable
Voldenet % and @ aren't even that different 13:51
Nemokosch anonymous state variables are kind of a niche either way
Voldenet they are big win for most one liners 13:54
tbrowder__ m: sub f($d) { $d * pi}; my $a = f 30; say $a; 14:27
camelia 94.24777960769379
tbrowder__ howdy, just checking syntax; i'm getting strange results in a prog i'm working on 14:29
tbrowder__ .ask ugexe is there a way to download the tgz file of a specifig distro version? 19:36
tellable6 tbrowder__, I'll pass your message to ugexe
ugexe tbrowder__: I'll probably add something one day. Right now `zef fetch` should probably do that, but right now it also runs the extraction step to make `zef fetch github.com/some/git/repo.git` Do The Right Thing. Unofficially though you can run `zef fetch Some::Module --/tar` and -- assuming Some::Module is a tar file and not a git repo -- it will download the file to a temp location, tell you 21:41
tellable6 2023-04-13T19:36:10Z #raku <tbrowder__> ugexe is there a way to download the tgz file of a specifig distro version?
ugexe that location, and then exit with an error (because it will fail to extract the file)
see gist.github.com/ugexe/18b87f96de8d...0e059701f8 21:43
tbrowder__ ugexe: thnx 22:42