Rules / Types, classes & roles / domain-specific

Attribute Reference

Member variable

What it is #

class Boo {

Routines #

Signatures are reproduced from the documentation, including their declared return types. A routine listed here is part of the type's published interface; whether Raku++ implements it is a separate question, answered by the examples below.

method new #

Creates a new attribute. The following named arguments are required: - $name contains the attribute's name, which should always be a

method name #

method name(Attribute:D: --> Str:D)

Returns Str:D.

Returns the name of the attribute. Note that this is always the private name, so if an attribute is declared as has $.a, the name returned is $!a.

method package #

method package()

Returns the package (class/grammar/role) to which this attribute belongs.

method has_accessor #

method has_accessor(Attribute:D: --> Bool:D)

Returns Bool:D.

Returns True if the attribute has a public accessor method.

method rw #

method rw(Attribute:D: --> Bool:D)

Returns Bool:D.

Returns True for attributes that have the "is rw" trait applied to them.

method readonly #

method readonly(Attribute:D: --> Bool:D)

Returns Bool:D.

Returns True for readonly attributes, which is the default, or False for attributes marked as is rw.

method required #

method required(Attribute:D: --> Any:D)

Returns Any:D.

Returns 1 for attributes that have the "is required" trait applied, or Mu if the attribute did not have that trait applied. If the "is required" trait is applied with a string, then that string will be returned instead of 1.

method type #

method type(Attribute:D: --> Mu)

Returns Mu.

Returns the type constraint of the attribute.

method get_value #

method get_value(Mu $obj)

Returns the value stored in this attribute of object $obj. Note that this method violates encapsulation of the object, and should be used with care.

method set_value #

method set_value(Mu $obj, Mu \new_val)

Binds the value new_val to this attribute of object $obj. Note that this method violates encapsulation of the object, and should be used with care. Here be dragons.

method gist #

multi method gist(Attribute:D:)

Returns the name of the type followed by the name of the attribute. Since say implicitly calls .gist, that is what produces the output here.

method is_built #

method is_built()

Returns True if the attribute had the is built trait applied to it, otherwise returns False.

method is_bound #

method is_bound()

Returns True if the attribute had the is built trait applied to it with :bind as an argument, otherwise returns False.

Examples, run three ways #

Every example below comes from the official documentation, together with the output that documentation asserts. Each was then executed by Rakudo and by Raku++ when this page was built. Where the three agree, one result is shown; where they do not, all three are — because which of them is wrong is exactly the information worth having.

2 all-differ · 19 no-output · 2 not-runnable · 8 ok · 3 rakupp-differs

class Attribute { }

Not executed: the documentation states no expected output for this example.

class WithAttributes {
has $.attribute;
has $.attribute-two-electric-boogaloo;
has $.yet-another-attribute;
}
.say for WithAttributes.^attributes(:local).map(*.name);
# OUTPUT:
# $!attribute
# $!attribute-two-electric-boogaloo
# $!yet-another-attribute

Not executed: the documentation states no expected output for this example.

class WithAttribute {
has $.attribute;
}

Not executed: the documentation states no expected output for this example.

BEGIN {
constant WithAttribute = Metamodel::ClassHOW.new_type: :name<WithAttribute>;
WithAttribute.^add_attribute: Attribute.new:
    :name<$!attribute>, :type(Any), :package(WithAttribute),
    :1has_accessor;
WithAttribute.^compose;
}

Not executed: the documentation states no expected output for this example.

class C {
    has $.a is default(42) is rw = 666
}
my $c = C.new;
say $c;
$c.a = Nil;
say $c;
# OUTPUT: «C.new(a => 666)␤C.new(a => 42)␤»
class Foo {
    has @.bar is default(42) is rw
};
my $foo = Foo.new( bar => <a b c> );
$foo.bar =Nil;
say $foo; # OUTPUT: «Foo.new(bar => [42])␤»
Documentation
C.new(a => 666)
C.new(a => 42)
Foo.new(bar => [42])
Rakudo
C.new(a => 666)
C.new(a => 42)
Foo.new(bar => [42])
Raku++
C.new(a => 666)
C.new(a => Nil)
Foo.new(bar => Nil)

Raku++ disagrees with both the documentation and Rakudo — a defect.

multi trait_mod:<is> (Attribute $attr, :$required!)

Not executed: the documentation states no expected output for this example.

class C {
    has $.a is required
}
my $c = C.new;
CATCH{ default { say .^name, ': ', .Str } }
# OUTPUT: «X::Attribute::Required: The attribute '$!a' is required, but you did not provide a value for it.␤»
Output
X::Attribute::Required: The attribute '$!a' is required, but you did not provide a value for it.

Documentation, Rakudo and Raku++ all agree.

class Power {
    has Numeric:D $.base     is required;
    has Numeric:D $.exponent is required;
    multi method Numeric(::?CLASS:D: --> Numeric:D) {
        $!base ** $!exponent
    }
}

Not executed: the documentation states no expected output for this example.

class D {
has $.a is required("it is a good idea");
}
my $d = D.new;
CATCH{ default { say .^name, ': ', .Str } }
# OUTPUT: «X::Attribute::Required: The attribute '$!a' is required because it is a good idea,␤but you did not provide a value for it.␤»
Output
X::Attribute::Required: The attribute '$!a' is required because it is a good idea,
but you did not provide a value for it.

Documentation, Rakudo and Raku++ all agree.

multi trait_mod:<is>(Attribute:D $r, :$DEPRECATED!)

Not executed: the documentation states no expected output for this example.

class C {
    has $.foo is DEPRECATED("'bar'");
}
my $c = C.new( foo => 42 );  # doesn't trigger with initialization (yet)
say $c.foo;                  # does trigger on usage

Not executed: the documentation states no expected output for this example.

# Saw 1 occurrence of deprecated code.
# =====================================
# Method foo (from C) seen at:
# script.raku, line 5
# Please use 'bar' instead.

Not executed: the documentation states no expected output for this example.

multi trait_mod:<is> (Attribute:D $attr, :$rw!)

Not executed: the documentation states no expected output for this example.

  has $.bar is rw;
  has $.baz;

Not executed: the documentation states no expected output for this example.

multi trait_mod:<is> (Attribute:D $attr, :readonly($)!)

Not executed: the documentation states no expected output for this example.

=begin code :skip-test<illustrates error>
class Thing is rw {
    has $.form;
    has $.matter is readonly;
};

Not executed: the documentation states no expected output for this example.

my $t = Thing.new(matter => "copper", form => "cubic");
$t.form = "round";   # OK, form is rw
$t.matter = "iron";  # not OK, matter is readonly
# OUTPUT: «Cannot modify an immutable Str (copper)␤...»
=end code

Neither engine can run this in isolation — the example depends on context from the surrounding text.

multi trait_mod:<is>(Attribute:D $a, :$built!)

Not executed: the documentation states no expected output for this example.

class Foo {
    has $!bar is built; # same as `is built(True)`
    has $.baz is built(False);
    has $!qux is built(:bind);

Not executed: the documentation states no expected output for this example.

    method bar(::?CLASS:D:) { $!bar }
    method qux(::?CLASS:D:) { $!qux }
}

Not executed: the documentation states no expected output for this example.

my Foo:D $foo .= new: :bar[], :baz[], :qux[];
say $foo.bar.raku; # OUTPUT: «$[]␤»
say $foo.baz.raku; # OUTPUT: «Any␤»
say $foo.qux.raku; # OUTPUT: «[]␤»

Neither engine can run this in isolation — the example depends on context from the surrounding text.

class Foo {
    has $!foo is built(:bind) = Proxy.new: :STORE{...}, :FETCH{...}
}

Not executed: the documentation states no expected output for this example.

method new(
Attribute:_:
:$name!,
:$type!,
:$package!,
:$inlined = 0,
:$has_accessor = 0,
:$is_built = $has_accessor,
:$is_bound = 0,
:$positional_delegate = 0,
:$associative_delegate = 0,
*%other
)

Not executed: the documentation states no expected output for this example.

class Foo {
    has @!bar;
}
my $a = Foo.^attributes(:local)[0];
say $a.name;            # OUTPUT: «@!bar␤»
Output
@!bar

Documentation, Rakudo and Raku++ all agree.

class Boo {
    has @!baz;
}
my $a = Boo.^attributes(:local)[0];
say $a.package;         # OUTPUT: «(Boo)␤»
Documentation
(Boo)
Rakudo
(Boo)
Raku++
(Mu)

Raku++ disagrees with both the documentation and Rakudo — a defect.

class Container {
    has $!private;
    has $.public;
}
my $private = Container.^attributes(:local)[0];
my $public = Container.^attributes(:local)[1];
say $private.has_accessor; # OUTPUT: «False␤»
say $public.has_accessor;  # OUTPUT: «True␤»
Output
False
True

Documentation, Rakudo and Raku++ all agree.

class Library {
    has $.address; # Read-only value
    has @.new-books is rw;
}
my $addr = Library.^attributes(:local)[0];
my $new-books = Library.^attributes(:local)[1];
say $addr.rw;      # OUTPUT: «False␤»
say $new-books.rw; # OUTPUT: «True␤»
Output
False
True

Documentation, Rakudo and Raku++ all agree.

class Library {
    has $.address; # Read-only value
    has @.new-books is rw;
}
my $addr = Library.^attributes(:local)[0];
my $new-books = Library.^attributes(:local)[1];
say $addr.readonly;      # OUTPUT: «True␤»
say $new-books.readonly; # OUTPUT: «False␤»
Output
True
False

Documentation, Rakudo and Raku++ all agree.

class Library {
    has $.address is required;
    has @.new-books is required("we always need more books");
}
my $addr = Library.^attributes(:local)[0];
my $new-books = Library.^attributes(:local)[1];
say $addr.required;      # OUTPUT: «1␤»
say $new-books.readonly; # OUTPUT: «"we always need more books"␤»
Documentation
1
"we always need more books"
Rakudo
1
True
Raku++

All three differ. Needs a human.

Not yet examined. Which of these is correct has not been established — do not treat either engine as settled here.

class TypeHouse {
    has Int @.array;
    has $!scalar;
    has @.mystery;
}
my @types = TypeHouse.^attributes(:local)[0..2];
for 0..2 { say @types[$_].type }
# OUTPUT: «(Positional[Int])
# (Mu)
# (Positional)␤»

Not executed: the documentation states no expected output for this example.

class Violated {
    has $!private-thing = 5;
}
my $private = Violated.^attributes(:local)[0];
say $private.get_value(Violated.new); # OUTPUT: «5␤»
Output
5

Documentation, Rakudo and Raku++ all agree.

class A {
    has $!a = 5;
    method speak() { say $!a; }
}
my $attr = A.^attributes(:local)[0];
my $a = A.new;
$a.speak; # OUTPUT: «5␤»
$attr.set_value($a, 42);
$a.speak; # OUTPUT: «42␤»
Output
5
42

Documentation, Rakudo and Raku++ all agree.

class Hero {
has @!inventory;
has Str $.name;
submethod BUILD( :$name, :@inventory ) {
    $!name = $name;
    @!inventory = @inventory
}
}
say Hero.^attributes(:local)[0]; # OUTPUT: «Positional @!inventory␤»
Documentation
Positional @!inventory
Rakudo
Positional @!inventory
Raku++
Mu @!inventory

Raku++ disagrees with both the documentation and Rakudo — a defect.

class Hangout {
    has $.table;
    has $.bar is DEPRECATED("the patio");
}
my $attr-table = Hangout.^attributes(:local)[0];
my $attr-bar = Hangout.^attributes(:local)[1];
with $attr-table.?DEPRECATED -> $text {     # does not trigger
    say "Table is deprecated with '$text'";
    # OUTPUT:
}
with $attr-bar.?DEPRECATED -> $text {
    say "Bar is deprecated with '$text'";
    # OUTPUT: «Bar is deprecated with 'the patio'"␤»
}
Documentation
Bar is deprecated with 'the patio'"
Rakudo
Bar is deprecated with 'the patio'
Raku++

All three differ. Needs a human.

Not yet examined. Which of these is correct has not been established — do not treat either engine as settled here.