This channel is intended for people just starting with the Raku Programming Language (raku.org). Logs are available at irclogs.raku.org/raku-beginner/live.html Set by lizmat on 8 June 2022. |
|||
00:03
Kaiepi left
00:27
MasterDuke joined
|
|||
zacque | What is the relationship between the key and value pair in “provides” field of a META6.json file? | 00:57 | |
It seems to me something like “JSON::Fast” : “lib/JSON/Fast.rakumod” is redundant? | 01:00 | ||
kjp | No. The key is the name of the mdule; the value is the file containing it. The names need not correspond. | 01:02 | |
zacque | Can I map different module name to some other module file? Or can I place multiple modules into one module file? | ||
kjp | I believe so. | ||
zacque | I see, I’ll try it out. Thanks! | 01:03 | |
01:53
MasterDuke left
01:57
frost78 joined
|
|||
elcaro | A simple way to solve this is implement a `.cmp` method on your class. being a method, it has access to private attributes, etc. Then you export `multi sub infix:<cmp>(MyClass $a, MyClass $b) { $a.cmp($b) }` | 02:00 | |
zacque | Thanks, question: How can I access the private attribute of the passed-in object? | 02:28 | |
<@724421839924756480> | 02:31 | ||
elcaro | Ahh, ok, I see your problem... You need access to both objects privates | ||
There is a way to break OO privacy: rosettacode.org/wiki/Break_OO_privacy#Raku | 02:38 | ||
there might be a smarter way to compare your objects. Is the data truly private? or are you just trying to make it private because the user doesn't need it? Can you perhaps expose some kind of hash of the private data, where you can then compare hashes? | 02:39 | ||
hashes as in... Digests... not Associative Arrays / Dictionaries | |||
zacque | Oh? I thought in ```raku | 02:40 | |
class A { | |||
has Int $!a; | |||
submethod BUILD(Int :$!a) { } | |||
method cmp(A $obj2) { $!a cmp $obj2.<!a>; } | |||
} | |||
``` `cmp` has access to the private attribute of `$obj2`. | |||
Oh? I thought in ```raku | 02:41 | ||
class A { | |||
has Int $!a; | |||
submethod BUILD(Int :$!a) { } | |||
method cmp(A $obj2) { ... } | |||
} | |||
``` `cmp` has access to the private attribute of `$obj2`. | |||
elcaro | No... Raku objects are not stored as a hash. You have to hit up the MOP to break into them | ||
zacque | Ya, I'm trying to make all attributes private by default, unless direct access is needed | ||
I see, that's unexpected | 02:43 | ||
elcaro | in that case it would be `$obj2.^attributes.first('$!a').get_value($obj2)`, but that's probably overkill if there's no _harm_ in exposing the data. | ||
What is unexpected... that they are not hashes underneath, or that privacy can be broken with the MOP? | 02:44 | ||
zacque | I meant the private attribute of object of the same class cannot be accessed directly | ||
What does the `first('$!a')` do here? | 02:46 | ||
Does it imply that there might be multiple attributes called `$!a`? | 02:48 | ||
elcaro | Yeah so the distinction is that attributes belong to the instance, not the class. | 02:50 | |
It's just occurred to me that objects are like people in that they have self-sovereignty. maybe I'm reading to much into things 😄 | |||
zacque | Oh, because that's the only method (besides `grep`) to lookup value from a list | ||
I'm still new to the List methods | |||
elcaro | yeah, it returns an item, rather than grep which returns a list (of possibly only one item) | 02:52 | |
The point is... if someone wants to break into your object, they can... but if they don't need to, they won't bother. | |||
In that case, you are just making it harder on yourself by making it private. | |||
zacque | Get it, thanks! In my case, the comparing data is a derived data, so I don't really want to expose it to the public | 02:54 | |
The client passes in a string for constructor, but I'm comparing based on derived data from the string, which has different order from comparing the strings directly. 😄 | |||
elcaro | If the object has access to the passed in value, perhaps it can re-derive it? but at the end of the day, it's your code... do what feels right | 02:58 | |
zacque | Oh no, the main reason to use the class is to encapsulate derivation and comparison logic | ||
Yup, thanks for your help! | |||
elcaro | a downside is the perf hit from constantly looking up a list of attributes and filtering. You could resolve the attribute lookup once. here's a silly trick | 03:04 | |
``` | |||
class Foo { | |||
has $.pub; | |||
has $!priv; | |||
has $!priv-attr = self.^attributes.first('$!priv'); | |||
submethod BUILD(:$!pub, :$!priv) { } | |||
method cmp(::?CLASS $foo) { | |||
$!priv eq $!priv-attr.get_value($foo) | |||
} | |||
} | |||
multi sub infix:<cmp>(Foo $l, Foo $r) { $l.cmp($r) } | |||
my $a = Foo.new(pub => 'a', priv => 'fo0B4R'); | |||
my $b = Foo.new(pub => 'b', priv => 'fo0B4R'); | |||
my $c = Foo.new(pub => 'c', priv => 'foobar'); | |||
say $a cmp $b; # True | |||
say $a cmp $c; # False | |||
``` | |||
zacque | Huh? What's weird is that a method can access the **private method** of object of the same class, but not its **private attribute** | 03:06 | |
See: ```raku | 03:07 | ||
use v6.d; | |||
class A { | |||
has Int $!a; | |||
submethod BUILD(Int :$!a) { } | |||
method cmp(A $obj2) { | |||
$!a cmp $obj2.^attributes.first('$!a').get_value($obj2) | |||
} | |||
method !foo() { $!a * 2; } | |||
# test private method access | |||
method test-pmthd(A $obj2) { $obj2!foo; } | |||
} | |||
my $foo1 = A.new(:7a); my $foo2 = A.new(:5a); | |||
say $foo1.cmp($foo2); | |||
say $foo1.test-pmthd($foo2); | |||
``` | |||
See: ```raku | 03:08 | ||
use v6.d; | |||
class A { | |||
has Int $!a; | |||
submethod BUILD(Int :$!a) { } | |||
method !foo() { $!a * 2; } | |||
# test private method access | |||
method test-pmthd(A $obj2) { $obj2!foo; } | |||
} | |||
my $foo1 = A.new(:7a); my $foo2 = A.new(:5a); | |||
say $foo1.test-pmthd($foo2); | |||
``` | |||
See: ```raku | |||
class A { | |||
has Int $!a; | |||
submethod BUILD(Int :$!a) { } | |||
method !foo() { $!a * 2; } | |||
# test private method access | |||
03:08
discord-raku-bot left
03:09
discord-raku-bot joined
|
|||
elcaro | oh yes, of course! | 03:09 | |
as I mentioned, attributes belong to the _instance_, but methods belong to the _class_... so you can just expose the private attribute *via* a private method | 03:11 | ||
so that other classes can access it | |||
zacque | See: ```raku | 03:13 | |
class A { | |||
has Int $!a; | |||
submethod BUILD(Int :$!a) { } | |||
method !foo() { $!a } | |||
# test private method access | |||
method test-pmthd(A $obj2) { $obj2!foo; } | |||
} | |||
my $foo1 = A.new(:7a); my $foo2 = A.new(:5a); | |||
say $foo1.test-pmthd($foo2); # Output: 5 | |||
``` | |||
elcaro | so you should just have a `method !a { $!a }`, | ||
then `method cmp($obj) { $!a cmp $obj!a }` | |||
zacque | Other classes? I thought only objects of the same class can access to the private method? | 03:15 | |
elcaro | yes, only same class | ||
I meant... other _instances_ | |||
zacque | Ya, just thought of that as well, still I think that a bit of weird UX | ||
elcaro | so that other ~~classes~~ _instances_ can access it | 03:16 | |
zacque | But that will solve my problem | ||
Ok | 03:17 | ||
Thanks! | |||
To sort out my mind, so a method has access to all attributes of the invocant and all methods of the same class | 03:21 | ||
But for objects passed in as an argument, it has only access to all its methods (be it private or public) | |||
But for objects passed in as an argument, the method has only access to all its methods (be it private or public) | 03:22 | ||
But only access to all methods for objects of the same class passed in as an argument. (By all, I meant both public and private) | 03:25 | ||
Only access to public methods for objects of different class | |||
elcaro | yes | 03:36 | |
It's worth noting that `has $.a` is really just syntax sugar for `has $!a; method a { $!a }` | |||
So the only way to expose an attribute... even a public one, is via a method (under the hood). | 03:38 | ||
In the same way, a private method can expose an attribute... the difference being private methods are only available to instances of that class | |||
zacque | Thx, I'm aware of it | 03:40 | |
04:14
Heptite left
|
|||
That said, there is no name conflict if I do this: ```raku | 04:49 | ||
class Foo { | |||
has $.a; | |||
method a { 100 } # No name conflict. | |||
} | |||
``` | |||
But something like this is illegal: ```raku | 04:50 | ||
class Bar { | |||
method a { 100 } | |||
method a { 200 } # Error! Same name conflict. | |||
} | |||
``` | |||
elcaro | Correct. Perhaps it's more correct to say `$!a` creates an accessor method `a`, unless you provide your own method with that name. | 05:09 | |
Correct. Perhaps it's more correct to say `$.a` creates an accessor method `a`, unless you provide your own method with that name. | 05:46 | ||
Nemokosch | I remember when learning OO (with C++), it seemed weird that private data can be reached from another instance that just has the same class but otherwise has nothing to do with `this` 😅 | 06:38 | |
I agree, though, that methods and attributes behave way too differently to be intuitive | |||
zacque | Lol, didn't think that much back then | 06:57 | |
Nemokosch | well we were there to learn | 06:59 | |
with one of the best teachers of the university | |||
07:09
Kaiepi joined
|
|||
zacque | That's great! | 07:17 | |
New question: How do I define multiple constructors for a class? | 07:21 | ||
Should I overload the `new` method or the `BUILD` method? | 07:23 | ||
08:12
dakkar joined
|
|||
Nemokosch | I can very vaguely recall something from Liz that TWEAK is better than BUILD? Anyway, almost sure new should do | 08:15 | |
discord.com/channels/5384078799804...5953687652 MasterDuke it was | 08:17 | ||
Nahita | at the BUILD and TWEAK phases the object has been already blessed, so new should be made multiple | 08:19 | |
its name need not be new but it's convention and default constructor has that name too. but you can call it `make` and as long as you end up blessing in that, it works | |||
naming it different useful in factory methods like `from-*` etc. | 08:21 | ||
i sometimes override and possibly abuse CALL-ME to type less | |||
09:28
dakkar left
09:29
dakkar joined
11:33
equinox joined
12:11
equinox36 joined
12:14
equinox left
|
|||
zacque | Hmm, I'm going for `make` as constructor | 12:17 | |
Couldn't figure out what's wrong with this: ```raku | |||
class Foo { | |||
has ($!x, $!y); | |||
multi method make(:$x, :$y) { | |||
say "Here x y"; | |||
self.bless(:$x, :$y) | |||
} | |||
multi method make(:$z) { | |||
say "Here z: $z"; | |||
self.bless(x => ($z div 2), y => ($z % 2)) | |||
} | |||
submethod BUILD(:$!x, :$!y) {} | |||
method result { "$!x and $!y" } | |||
} | |||
Foo.make(:2x, :3y).result.say; # Ok | |||
Foo.make(:4z).result.say; # Uninitialised Error | |||
``` | |||
It seems like I should be able to pass `:z` into `Foo.make` but it didn't | |||
Very confusing... | |||
Nemokosch | as you can see, the first function runs | 12:25 | |
making named _optional_ arguments is probably not a good idea if you want to dispatch over named arguments | |||
changed it to :$x! and :$y! and it worked | |||
lizmat | indeed: named optional arguments are not being used in dispatch | 12:27 | |
zacque | Huh? What do you mean by "named optional arguments"? | 12:32 | |
From my POV, all arguments are compulsory? | 12:33 | ||
Nemokosch | no, named arguments are optional by default | ||
zacque | Huh? I don't get this | ||
Nemokosch | why not :c | ||
zacque | Oh nooo, I didn't know 😦 | ||
Oh... you mean `multi method make(:$x!, :$y!)`? | 12:34 | ||
Didn't know about that as well, let me look it up | 12:35 | ||
I found it: rakudocs.github.io/type/Signature#..._arguments | 12:37 | ||
Thanks, that solves my problem! | 12:41 | ||
Not sure why these small details keep escaping me 🤦♂️ | 12:42 | ||
12:42
equinox36 left
|
|||
lizmat | well... what if all named arguments were taken into dispatch, it would get a lot more complicated and probably much slower to dispatch | 12:48 | |
by making named arguments mandatory, they effectively become positionals as far as dispatch is concerned | 12:49 | ||
zacque | Makes sense... | 13:00 | |
13:01
frost78 left
13:02
Newbie21 joined
13:04
jgaz joined
|
|||
Newbie21 | I'm trying to install Rakudo Star under WSL but the instructions seem out of date. Are there update instructions available? ( rakudo-star-2022.07-01.tar.gz ) | 13:08 | |
*updated | 13:09 | ||
13:29
equinox joined
|
|||
Nemokosch | if you accept an X-Y solution: you might be better off using rakubrew under WSL, that's what I use myself | 13:33 | |
Newbie21 | Will look into that. | 13:40 | |
14:34
Heptite joined
16:09
razetime joined
16:34
dakkar left
16:46
Heptite left
17:05
m_athias left
17:06
razetime left,
camelia left
17:10
m_athias joined
17:12
camelia joined
17:14
m_athias left,
camelia left
17:15
m_athias joined
17:23
camelia joined
17:34
Heptite joined
17:59
saint- joined
19:33
jgaz left
20:26
habere-et-disper joined
20:59
Newbie21 left
21:34
habere-et-disper left
21:40
equinox left
23:10
archenoth left
23:17
deoac joined
|