Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assigning values to attributes in the BUILD phaser for an object

Tags:

oop

raku

When a BUILD phaser is called, it overrides default attribute assignment in Perl6. Suppose we have to use that BUILD phaser, like we do in this module (that's where I met this problem). What's the way of assigning values to attributes in that phase? I have used this

class my-class {
    has $.dash-attribute;

    submethod BUILD(*%args) {
        for %args.kv -> $k, $value {
            self."$k"( $value );
        }
    }
};

my $my-instance = my-class.new( dash-attribute => 'This is the attribute' );

And I get this error

Too many positionals passed; expected 1 argument but got 2

Other combinations of $!or $., direct assignment, declaring the attribute as rw (same error) yield different kind of errors. This is probably just a syntax issue, but I couldn't find the solution. Any help will be appreciated.

like image 994
jjmerelo Avatar asked Mar 17 '18 09:03

jjmerelo


2 Answers

There are two things wrong in your example, the way I see it. First of all, if you want an attribute to be writeable, you will need to mark it is rw. Secondly, changing the value of an attribute is done by assignment, rather than by giving the new value as an argument.

So I think the code should be:

class my-class {
    has $.dash-attribute is rw;

    submethod BUILD(*%args) {
        for %args.kv -> $k, $value {
            self."$k"() = $value;
        }
    }
};

my $my-instance = my-class.new( dash-attribute => 'attribute value' );
dd $my-instance;
# my-class $my-instance = my-class.new(dash-attribute => "attribute value")
like image 84
Elizabeth Mattijsen Avatar answered Sep 29 '22 21:09

Elizabeth Mattijsen


You could do it the same way the object system normally does it under the hood for you.
(not recommended)

class C {
  has $.d;

  submethod BUILD ( *%args ){
    for self.^attributes {
      my $short-name = .name.substr(2); # remove leading 「$!」
      next unless %args{$short-name}:exists;
      .set_value( self, %args{$short-name} )
    }
  }
}

say C.new(d => 42)
C.new(d => 42)
like image 35
Brad Gilbert Avatar answered Sep 29 '22 23:09

Brad Gilbert



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!