🦋 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.
guest912 Can I create a custom hash type overriding x{smth} operation? 00:02
So that smth could be not a string but converted to a string under the hood?
I’m trying to add “does Associative [K,V]”, adding AT-KEY & ASSIGN-KEY methods but when I try to do x{smth} I get an error 00:03
Like “Associative indexing implementation missing from type”
guifa Yes 00:07
you can override the AT-KEY method
what's the error? 00:08
guest912 I did that, but I get this “Associative indexing implementation missing from type”
My type name after this
guifa do you also have an EXISTS-KEY method? I'm pretty sure it's just AT-KEY and EXISTS-KEY that are the minimum 00:09
guest912 Yep 00:18
guifa can you post your code?
guest912 Let me try some make some clean example
guest912 guifa, here: pastebin.com/SJb6sHka 00:33
An attempt to read (“a{(12,34)}.say”) gets me the same error 00:46
Wait, value type comes first, before the key? role Associative[::TValue = Mu, ::TKey = Str(Any)] { } 00:47
It does not change my error though
guest912 I removed “multi” and used regular methods 00:51
It fixed the issue but now I have another issue 00:52
nemokosch there are too many type annotations for me to feel comfortable 😄
guest912 pastebin.com/yBjghHc8 00:53
I tries to destructure the key into multiple different keys. Even though I add a scalar wrapper. 00:54
Dam, it was not a scalar wrapper but a list wrapper
My bad
It seems to work, let me check
avuserow m: sub f(--> Int, Int) {return 1, 2;}; say f(); # is there a way to specify multiple returned items in the signature? 00:55
camelia ===SORRY!=== Error while compiling <tmp>
Malformed return value (return constraints only allowed at the end of the signature)
at <tmp>:1
------> sub f(--> Int⏏, Int) {return 1, 2;}; say f(); # is the
avuserow m: sub f(--> (Int, Int)) {return 1, 2;}; say f(); # is there a way to specify multiple returned items in the signature? 00:56
camelia ===SORRY!=== Error while compiling <tmp>
Malformed return value
at <tmp>:1
------> sub f(-->⏏ (Int, Int)) {return 1, 2;}; say f(); #
guest912 Okay this works: pastebin.com/t7JD0FMZ 01:00
avuserow, I would define a type that describes this shape and return it 01:01
m: subset IntPair where * ~~ (Int:D, Int:D); sub foo(--> IntPair:D) { (12,34) }; foo.say 01:02
camelia (12 34)
guest912 Is there any point to add any parameters to Associative role? 01:07
If I change them to any random types (“Associative[Bool:D, UInt:D]”) everything works as before
Is it just purely some metadata, just like code comments?
guifa I don't think I've ever used it, would need to investigate it a bit more. I think the idea would be that you would say Associative[::K, ::V] and then have, e.g. method of { V } 01:12
but don't quote me on that
guest912 docs-dev.raku.org/type/Associative in the docs it seems like the value comes before the key 01:16
role Associative[::TValue = Mu, ::TKey = Str(Any)] { }
nemokosch I don't know, check is a bit frightening 01:18
pastebin.com/yBjghHc8 - this snippet was quite certainly about the way indexing is hooked into AT-POS
namely that it has loads of clever dispatches, and they quite certainly include list-y dispatches
that's why something like %foo{1, 2, 3} could work as %foo{1}, %foo{2}, %foo{3} 01:19
guest912 It seems the whole “does Associative” is not necessary
nemokosch it probably isn't, maybe the sigil checks it
guifa the role is required for the sigil, but that's about it 02:05
assigning to @ requires Positional, to % Associative, and & Callable (callable or code I forget which lol)
nemokosch Callable 02:10
[Coke] came back hours later, that scraper test still running 02:31
guest912 guifa, so those parameters for the role is purely documentation? 02:33
Or you can somehow actually access them?
nemokosch no, it's rather the role itself that is mostly for documentation 02:43
[Coke] scrape() calls out to from-xml($data), that hangs. 03:15
[Coke] this hangs in a checkout of web scraper: raku -I. -MXML -e "from-xml('t/data/s05.html'.IO.slurp)" 03:41
github.com/raku-community-modules/XML/issues/68 03:45
guifa guest912: no, not necessarily. The parameters autofill for of and keyof 04:02
m: class A {;}; class B {;}; class Foo does Associative[A,B] {;}; say Foo.of; say Foo.keyof
camelia (A)
(B)
guest912 guifa, can I somehow access these in the type signature of a method? 04:07
Like class A does Associative[Int:D, Str:D] { method AS-KEY(self.keyof \x --> self.of) {} }
guifa I mean, sure, ... where self.of and where self.keyof. But you could just hard code them since they're known at compile time 04:08
guest912 I just want this for the sake of having a shorthand 04:10
guest912 The types can be long, nested into multiple package levels 04:10
guifa class Foo does Associative { my \K = Foo.keyof; my \V = Foo.of; method ASSIGN-KEY($k where K, $v where V) { say $k,$v } }; 04:12
guest912 guifa, what about return value? 04:44
Return type I mean
m: class Foo does Associative[Str:D, Int:D] { method ASSIGN-KEY(\k where Foo.keyof, \v where Foo.of) { say k, v } }; my \x = Foo.new; x{123} = 'hi'; 04:45
camelia 123hi
guest912 m: class Foo does Associative[Str:D, Int:D] { method ASSIGN-KEY(\k where Foo.keyof, \v where Foo.of) { say k.raku, ' ', v.raku } }; my \x = Foo.new; x{123} = 'hi'; 04:46
camelia 123 "hi"
guest912 m: class Foo does Associative[Str:D, Int:D] { method ASSIGN-KEY(\k where Foo.keyof, \v where Foo.of) { say k.raku, ' ', v.raku } }; my \x = Foo.new; x{123} = 321;
camelia Constraint type check failed in binding to parameter 'v'; expected anonymous constraint to be met but got Int (321)
in method ASSIGN-KEY at <tmp> line 1
in block <unit> at <tmp> line 1
guest912 m: class Foo does Associative[Str:D, Int:D] { subset V where Foo.of; method AT-KEY(\k where Foo.keyof --> V) {'test'}; method ASSIGN-KEY(\k,\v) {say k,v} }; my \x = Foo.new; x{123} = 'foo'; x{123}.raku.say 04:51
camelia 123foo
"test"
guest912 m: class Foo does Associative[Str:D, Int:D] { subset V where Foo.of; method AT-KEY(\k where Foo.keyof --> V) {321}; method ASSIGN-KEY(\k,\v) {say k,v} }; my \x = Foo.new; x{123} = 'foo'; x{123}.raku.say
camelia 123foo
Type check failed for return value; expected Foo::V but got Int (321)
in method AT-KEY at <tmp> line 1
in block <unit> at <tmp> line 1
guest912 guifa, it seems to me using subsets like “subset K where Foo.keyof” instead of “my \K = Foo.keyof” is better since you don’t have to type “Foo.*” all the time 04:52
In case you rename the class only a couple lines with those subsets will change.
Would you agree? 04:53
An the arguments become extremely short: K \k, V \v 04:54
Here is an example: pastebin.com/0iYev8EY 04:58
guest912 Is there an opposite of “:D” for the types? Like if a type is “:D” but you want to make it optional? 06:21
nemokosch Hm, what would that mean? 06:48
Sounds like an oxymoron to me
m: my Str:D %demo; %demo.of.&dd 06:52
Raku eval Str:D
nemokosch m: my Str:D %demo; %demo.of.WHAT.&dd 06:53
Raku eval Str:D
nemokosch Okay but what type is this xD
m: dd Str:D 06:54
Raku eval Str:D
nemokosch m: Str:D.^name.say
Raku eval Str:D
nemokosch Why...
m: my Str:D $nonsense = Str:D; dd $nonsense 06:55
Raku eval Exit code: 1 Type check failed in assignment to $nonsense; expected type Str:D cannot be itself (perhaps Nil was assigned to a :D which had no default?) in block <unit> at main.raku line 1
nemokosch Okay, this is ugly but at least comprehensible 06:56
guest912 Everything is nullable by default. 06:59
m: my Str $x = Nil; $x.say
camelia (Str)
guest912 Which is a mystery to me, why would anyone think it’s a good decision? 07:00
Like NullPointerException in Java was not enough as a proof that it is not
But in Java at least primitives are not nullable 07:02
nemokosch If you think it's a bad decision, what do you think about Str:D somehow being a value?
I've been using this language for more than two years and this is the first time I bumped into this
m: Str:D ~~ Str andthen say 07:03
Raku eval Exit code: 1 ===SORRY!=== Argument to "say" seems to be malformed at /home/glot/main.raku:1 ------> Str:D ~~ Str andthen say⏏<EOL> Other potential difficulties: Unsupported use of bare "say". In Raku please use: .say if you meant to call it as a method on $_, or use an explicit invocant or argument, or use &say to refer to the function as a noun. at /home/glot/main.raku:1 ------> Str:D ~~ Str
andthen say⏏<EOL>
nemokosch m: Str:D ~~ Str andthen .say
Raku eval True
guest912 I don’t think it’s a value, I just don’t want a variable to be able have Nil as value unless I asked for it explicitly
nemokosch You can see it is though 07:04
guest912 m: say Str:D ~~ Str
camelia True
guest912 nemokosch what do you mean I can see it?
nemokosch You can see that it is a value 07:05
It was a value in all these snippets
guest912 Are maybe referring to some Raku-related term “value”?
nemokosch No, common sense
You couldn't just print int or something in Java 07:06
guest912 From the common sense for me Str:D is a type that is saying explicitly that it is a non-nullable string
nemokosch Have you see the snippets though
guest912 What snippets?
nemokosch Here in the chat 07:07
guest912 I don’t think I see what you are talking about.
nemokosch And I'm not suited to run these circles at this hour 07:08
guest912 Anyway, all I want is to be explicit when I need an optional/nullable value or a defined one. 07:09
And I also want the type system to make sure the code is obeying the type constraints.
Voldenet in java Integer can be null though
guest912 Because Integer is not primitive? 07:10
Voldenet Right, raku's Int is java's Integer 07:11
java's int is raku's int32
m: my int32 $i; say $i;
camelia 0
guest912 m: my int32 $i = Nil; $i.say 07:12
camelia Cannot unbox a type object (Nil) to int.
in block <unit> at <tmp> line 1
guest912 m: my int32 $i; $i.say
camelia 0
guest912 m: my int32 $i; $i.defined.say
camelia True
guest912 Very similar to Java indeed
nemokosch Well, both int in Java and int32 in Raku are unnice low-level hacks 07:13
int32 is quite literally runtime-native 32-bit integer
Voldenet in C# Int32 is int, because C# has value type semantics via struct 07:14
which shows that you can solve that without those low-level hacks
nemokosch Yeah C# is a well-designed language for something as complex 07:15
Voldenet C# was designed to be able to describe C++/C headers
so it has __arglist, structs, stackalloc and all weird things 07:16
but still, I do believe that value semantics are really useful 07:17
in fact, raku has this problem, that native calling something with a struct is impossible
btw, I do wonder if using Int:D is going to be faster than Int 07:19
since Int:D is probably doing explicit typecheck and Int uses rare branch only when trying to unbox null 07:20
nemokosch look, the thing is, up until now I thought Int was two things: a value (the default value of type Int) and a type 07:21
I thought this was a specialty for type names that they fill both roles
But apparently Int:D is also a value, it is a value of Int, moreover a value of Int:D which is simply explicitly ruled out from assignment 07:22
Voldenet it's… sufficiently weird
nemokosch I thought it was only a type on an almost syntax level, therefore I thought asking "what type is it" would either be nonsense like in Java, or yield some meta type called Type or whatever 07:23
Voldenet m: my Int $u = Int:U; say $u; my Int $d = Int:D; say $d; my Int $i = Int; say $i; my Int:D $nd = Int:D;
camelia (Int:U)
Type check failed in assignment to $nd; expected type Int:D cannot be itself (perhaps Nil was assigned to a :D which had no default?)
in block <unit> at <tmp> line 1

(Int:D)
(Int)
Voldenet weird, the output is kind of reshuffled 07:24
either way, those Int… variants are simply pointers to some constants with no value 07:26
m: say Int =:= Int:U
camelia False
nemokosch why is it False anyway
why is it not the same at least 07:27
m: say Int =:= Int:T
Raku eval Exit code: 1 ===SORRY!=== Error while compiling /home/glot/main.raku Invalid type smiley ':T' used, only ':D', ':U' and ':_' are allowed at /home/glot/main.raku:1 ------> say Int =:= Int:T⏏<EOL> expecting any of: pair value
nemokosch m: say Int =:= Int:_
Raku eval True
nemokosch blah
Voldenet =:= basically checks pointer address
so it's obvious if those three are not equivalent 07:28
nemokosch it is obvious but why are they not, really 07:29
why are these fantom values backing all of them
and why do these fantom values fall into the same type
and look, here is the crazy thing 07:30
not long after saying that Int:D is an Int, it turns out Int:D doesn't even have a compatible meta-object!
m: (Int:D).^methods.say
Raku eval Exit code: 1 No such method 'methods' for invocant of type 'Perl6::Metamodel::DefiniteHOW' in block <unit> at main.raku line 1
nemokosch but somehow it's still hacked as if it indeed knew these methods 07:31
m: (Int:D).cos.say
Raku eval Exit code: 1 Use of uninitialized value of type Int:D in numeric context in block <unit> at main.raku line 1
nemokosch suddenly this call succeeded 07:32
or well, did it
at least some effort has been made to understand it as a number
Voldenet that behavior of ^methods makes sense, being able to assign Int:D to Int… 07:33
I'm betting nowhere it's described that it'd make sense
it only happens to work now
guest912 m: my Int:D $x = 123; my Int $y = $x; $y.say
camelia 123
Voldenet what I mean is\ 07:34
m: my Int $x = Int:D;
camelia ( no output )
nemokosch uh
Voldenet Int:D is not Int:D
Obviously :)
nemokosch but it is Int
XD
Voldenet no, it is not, Int =:= Int:D says False! :D
guest912 m: my Int $x = Int:D; say $x ~~ Int:D
camelia False
Voldenet m: my Int $x = Int:D; say $x ~~ Int:D; say $x 07:35
camelia False
(Int:D)
nemokosch but here's the thing
guest912 m: say Int ~~ Int 07:36
camelia True
nemokosch assignment succeeded to an Int type constraint
guest912 m: say Int:D ~~ Int:D
camelia False
nemokosch m: my Int $x = Int:D; my Int:D $y = $x;
Raku eval Exit code: 1 Type check failed in assignment to $y; expected type Int:D cannot be itself (perhaps Nil was assigned to a :D which had no default?) in block <unit> at main.raku line 1
nemokosch this is a big fat godforsaken nonsense
Int:D is Int but not Int:D
Voldenet m: my Int $x := Int:D; say $x ~~ Int:D; say $x =:= Int:D; say $x
camelia False
True
(Int:D)
Voldenet makes you scratch your head a bit 07:37
nemokosch a bit you say
Voldenet if you see pointers here and there, know that := copies the value 07:38
and ~~ compares the value
guest912 This seems very wrong: “my Int $x := Int:D; say $x ~~ Int:D;”
To be True
Voldenet this isn't, the =:= is
nemokosch btw I found how to make Int:D into Int 07:39
guest912 Ah, it’s actually False, it’s fine. I got confused by multiple says
guest912 m: my Int $x = Int:D; say $x =:= Int:D 07:40
camelia False
guest912 How was that True above? 07:41
Ah, it’s bind operator
:= vs. =
nemokosch m: (Int:D).^nominalize.say 07:42
Raku eval (Int)
nemokosch m: (Str:D).^nominalize.say
Raku eval (Str)
Voldenet it makes sense, though I'd rather have Int:D present itself as nominalized version after being assigned (not bound) to int 07:47
lizmat m: dd Int:D 09:33
camelia Int:D
lizmat m: my $x = Int:D; dd $x 09:34
camelia Mu $x = Int:D
lizmat m: say Int:D
camelia (Int:D)
lizmat m: my Int $x = Int:D; say $x<> =:= Int:D 09:35
camelia True
lizmat the problem was containerization of $x
=:= doesn't decontainerize 09:36
nemokosch The way this works isn't remotely alright 12:09
But at least found a way to "remove the type smiley"
tbrowder__ tonyo: i sent the pm 12:28
tbrowder__ is there an IRC channel for noob mac users who want to use the terminal? 12:30
tbrowder__ ah, i found a good link to lots of help 15:50
librasteve guest912: this is a bit late in the proceedings, you may want to look at raku.land/zef:lizmat/Hash::Agnostic 17:48
guest912: there are a couple of ways to adapt raku to use Monads such as github.com/masukomi/Definitely and github.com/rawleyfowler/Monad-Result/tree/main 18:05
Voldenet imo generic monads are not good fit for dynamic languages 18:15
Sure, you can code like this and it'll work, just the language itself prefers `given $x { when Int:D { }; default { }}` sort of syntax 18:18
antononcube @Voldenet I forgot to further troll @rf about his monads...
Basiscally, for me the forward feed operator provides good enough monadic pipelining. I do have complains about it, but they are relatively minor. 18:19
Voldenet feed operator is good overall 18:22
my biggest complaint is that for some reason topic variable is the last parameter 18:23
nemokosch is it really the topic variable, or just the passed value?
Voldenet well, it's passed value in this case 18:24
it's not gamebreaking, it only feels weird and creates hard to debug problems
ugexe feed operator was prohibitively slow last i remember
Voldenet especially if you change positional signatures without changing call sites
nemokosch I think it makes sense since for .& it's the first argument
aaand that's a big reason why I like it much more 18:25
the feed operator is almost never convenient to use, it takes way too special circumstances, not really worth keeping in your vocab
antononcube @Voldenet Yes! It is different from other languages I used monads with... I learned to live with it, though.
Voldenet .& has a few problems compared to feed op 18:26
antononcube @nemokosch I think you are thinking like a JavaScript programmer.
Voldenet m: sub inc($by, $n) { $n + $by }; 1 ==> inc(2) ==> inc(3) ==> say();
camelia 6
Voldenet now, the same thing done with .& is… ugh… not elegant 18:27
antononcube I like forwared feed, ==> , because code with it looks "pretty and instructive". 🙂
nemokosch why is it not elegant?
how is it not way better, even?
antononcube @Voldenet Good example. My main complaint is that we have to say() , not just say. 18:28
Voldenet m: sub inc($n, $by) { $n + $by }; 1.&inc(2).&inc(3).say;
camelia 6 18:29
Voldenet m: sub inc($n, $by) { $n + $by }; 1 . &inc(2) . &inc(3) .say;
camelia ===SORRY!=== Error while compiling <tmp>
Unsupported use of . to concatenate strings. In Raku please use: ~.
at <tmp>:1
------> sub inc($n, $by) { $n + $by }; 1 .⏏ &inc(2) . &inc(3) .say;
Voldenet uh oh
.& pretty much never allows spaces
if you did a lot of feed forward calls, it gets unreadable fast
nemokosch I mean who cares about spaces 18:30
I agree that it would be better if Raku wasn't this whitespace sensitive in general
Voldenet …astronomers?
nemokosch but I still think it's better in all regards 18:31
Voldenet I like whitespace rules compared to perl
nemokosch if somebody REALLY wants extra spaces, they should use the "unspace"
or andthen
I think the andthen chaining is still very much superior to feeds
Voldenet but you can say .map({ }) and .say on separate lines! 18:32
nemokosch I'm with Mr Krňávek on this one
yeah but it's kind of an inconsistent feature
Voldenet andthen is verbose
nemokosch ==> plus parens is also verbose, let's be fair 18:33
Voldenet True
nemokosch except it scales much worse lol
Voldenet and the uncanny thing about `==> thing(2)` is that uncanny last argument creeping in
I'd understand `==> thing(2, _)` and likes 18:34
nemokosch well I still think that since there is already .&, there would have been no point to feed it as first argument
Voldenet though I use feed forward more than .& only because of spaces and newlines 18:35
not that it's better
librasteve on the Option/Some/None Monads, I have spent a bit of time in Rust and, while I do not like shouty compilers htat prevent me from doing practically anything, I accept that Rust has it's adherents and that there is some sense in applying Monad restrictions where you want to surface possible (null-related) bugs early 18:47
so, I like that Raku will just get on and compile my stuff and let's me have undefined things here and there and fails quietly (as you say Voldenet) - but I also get that others may prefer a more shouty / safety-first alternative 18:49
Voldenet different languages, approaches and purposes 18:57
librasteve sure - imo (i) raku lets you code in the style you want and (ii) raku has the tools (in this case, a module or two) to let you do that if you want (for any that) 19:15
nemokosch the problem is that even after 2 years, there are these things in Raku that I've never seen and that make no sense 19:19
like this Int:D madness
it really feels like there was no design review/finalization, somebody at some point just said "okay, it's time to release something to the public"
librasteve well I don't suppose that anyone tried something as dumb as my Int $i = Int:D before ... so please fix it or shut up 19:23
nemokosch Fix it? This is ironic from somebody who actively opposes fixing design mistakes 19:54
No, let's just pretend problems don't exist
Or even better: blame the user for conceptual anomalies. Because why would anyone write complex or abstract code in Raku, right? Not possible. 19:55
Voldenet no need to get upset over it as long as we all agree it's silly 20:21
unless there's sound reason for all of this 20:22
nemokosch heh, as long as we agree 20:54
I find it so grotesque - somewhat offensive even, not gonna lie - that some people notoriously protect a programming language and its faults over actual people 20:55
inb4 no, I'm far from the only one, a lot more damage is done to actual beginners who legitimately got confused when something seriously strange is explained to them as a "you thing" 20:57
[Coke] heads out 21:22
guest912 librasteve thanks for the links. But the way how I use Raku and what I use it for implies that I have zero dependencies, and no depenencies management apart from the Rakudo itself. 21:42
So I either rely on builtin language features. Or something small I can add into the code itself. 21:43
Voldenet, “monads are not good fit for dynamic languages” yet we have them all over the place, like elvis operator for instance