Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mixed-in object variables available in mixed-in role declaration

Tags:

class

mixins

raku

I was wondering how to mix in an abstract role into a variable in runtime. Here's what I came up with

role jsonable {
    method to-json( ) { ... }
}

class Bare-Word {
    has $.word;
    method new ( Str $word ) {
        return self.bless( $word );
    }
}

my $that-word = Bare-Word.new( "Hola" ) but role jsonable { method to-json() { return "['$!word']"; } };

However, this throws an (perfectly reasonable) error:

$ perl6 role-fails.p6
===SORRY!=== Error while compiling /home/jmerelo/Code/perl6/dev.to-code/perl6/role-fails.p6
Attribute $!word not declared in role jsonable
at /home/jmerelo/Code/perl6/dev.to-code/perl6/role-fails.p6:14
------> hod to-json() { return "['$!word']"; } }⏏;
    expecting any of:
        horizontal whitespace
        postfix
        statement end
        statement modifier
        statement modifier loop

$!word belongs to the class, so it is not available as such in the mixin declaration. However, but is simply a function call so the declared variable should be available inside, right? What would be the right syntax to access it?

like image 762
jjmerelo Avatar asked Jan 06 '18 08:01

jjmerelo


1 Answers

The right syntax would be $.word, which is basically short for self.word, so it uses the public access method.

But I think there are some typos and some misconceptions here. The typo (I think) is that .bless only takes named parameters, so instead of $word, it should be :$word (turning a positional to word => $word). Also, a role that defines but not implements a method, and then use the same name to implement a role with that name, doesn't make sense. And I'm surprised it doesn't generate an error. So get rid of it for now. This is my "solution":

class Bare-Word {
    has $.word;
    method new ( Str $word ) {
        return self.bless( :$word );  # note, .bless only takes nameds
    }
}

my $that-word = Bare-Word.new( "Hola" ) but role jsonable {
    method to-json() {
        return "['$.word']"; # note, $.word instead of $!word
    }
}

dd $that-word; # Bare-Word+{jsonable}.new(word => "Hola")

Hope this helps.

like image 155
Elizabeth Mattijsen Avatar answered Jan 04 '23 00:01

Elizabeth Mattijsen