Q:

Assigning values to attributes in the BUILD phaser for an object

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.

A:

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")

A:

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)

