Declaring a variable belonging to a user-defined class in Perl 6

When you write my Int $a; you will have a variable of type Int, but without value, or even container. The concrete value of $a will be (Int).

The same with my House $house; - you will get (House) value.

In your case you have to initialize array's elements by some House value. For example:

my @houses = House.new() xx 11;
@houses[10].area = 222;

I think you're missing the part that the compiler is doing some of the work for you. When you have a literal number, the parser recognizes it and constructs the right numeric object for it. There's a virtual and unseen Int.new() that has already happened for you in rakudo/src/Perl6/Actions.nqp. It's at the NQP level but it's the same idea.


my House $a does the same as my Int $a. It puts a restriction on the values that you can put in it. If you look at the content of the variable, you will get the type object of that restriction.

There is a trick that you can use though, so you don't have to repeat the House bit: my House $a .= new, which is the equivalent of my House $a = House.new.

To get back to your question: yes, you can do that with some trouble:

class House {
    has $.area;
    multi method area(House:U \SELF:) is raw {
        (SELF = House.new).area
    }
    multi method area(House:D:) is raw {
        $!area
    }
}
my House @houses;
@houses[2].area = 42;
say @houses  # [(House) (House) House.new(area => 42)]

We create two candidates for the accessor method: one taking an undefined type object, and the other an instantiated object. The first one modifies its invocant (assuming it to be a container that can be set), then calls the instantiated version of the method. I'm leaving this as an exercise to the reader to turn this into an Attribute trait.

Tags:

Raku