class Attribute

Member variable
class Attribute { }

In Raku lingo, an attribute refers to a per-instance/object storage slot. An Attribute is used to talk about classes' and roles' attributes at the metalevel.

Normal usage of attributes does not require the user to use this class explicitly.

Traits

Trait is default

An attribute that is assigned Nil will revert to its default value set with the trait is default. In the case of arrays or associatives, the argument of is default will set the default item value or hash value.

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])␤»

Trait is required

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

The trait is required will mark the attribute as to be filled with a value when the object is instantiated. Failing to do so will result in a runtime error.

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.␤»

This trait also allows attributes to be typed with types that have a :D smiley without giving them a default value:

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

Available as of 6.d language version (early implementation exists in Rakudo compiler 2018.08+): You can specify a reason why the attribute is required:

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.␤»

is required doesn't just affect the default constructor, it checks for the attribute at a lower level, so it will work for custom constructors written using bless.

trait is DEPRECATED

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

Marks an attribute as deprecated, optionally with a message what to use instead.

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

After the program is finished, this will show something like this on STDERR:

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

trait is rw

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

Marks an attribute as read/write as opposed to the default readonly. The default accessor for the attribute will return a writable value.

class Boo {
      has $.bar is rw;
      has $.baz;
   };
my $boo = Boo.new;
   $boo.bar = 42; # works
   $boo.baz = 42;
   CATCH { default { put .^name, ': ', .Str } };
   # OUTPUT: «X::Assignment::RO: Cannot modify an immutable Any␤»

trait is built

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

By default, this trait allows setting up a private attribute during object construction via .new. The same trait can be used to prevent setting up a public attribute via .new by passing it the Boolean value False.

class Foo {
        has $!bar is built; # same as `is built(True)`
        has $.baz is built(False);
method bar {
            $!bar
        }
    }
my $foo = Foo.new(bar => 1, baz => 2);
    say $foo.bar; # OUTPUT: «1␤»
    say $foo.baz; # OUTPUT: «Any␤»

Available as of the 2020.01 release of the Rakudo compiler.

Methods

The usual way to obtain an object of type Attribute is by introspection:

class Useless {
        has @!things;
    }
    my $a = Useless.^attributes(:local)[0];
    say $a.raku;            # OUTPUT: «Attribute.new␤»
    say $a.name;            # OUTPUT: «@!things␤»
    say $a.package;         # OUTPUT: «(Useless)␤»
    say $a.has_accessor;    # OUTPUT: «False␤»

Modifying a private attribute from the outside is usually not possible, but since Attribute is at the level of the metaclass, all is fair game.

method name

method name(Attribute:D: --> 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.

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

method package

method package()

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

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

method has_accessor

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

Returns True if the attribute has a public accessor method.

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␤»

method rw

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

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

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␤»

method readonly

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

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

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␤»

method required

method required(Attribute:D: --> 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.

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"␤»

method type

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

Returns the type constraint of the attribute.

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)␤»

method get_value

method get_value(Mu $obj)

Returns the value stored in this attribute of object $obj.

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

Note that this method violates encapsulation of the object, and should be used with care. Here be dragons.

method set_value

method set_value(Mu $obj, Mu \new_val)

Binds the value new_val to this attribute of object $obj.

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␤»

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.

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

Since say implicitly calls .gist, that is what produces the output here.

Optional introspection

DEPRECATED

If an attribute is marked as DEPRECATED, then calling the DEPRECATED method is possible and will return "something else" (if no specific reason was specified) or the string that was specified with the DEPRECATED trait.

If an attribute is not marked as DEPRECATED, one cannot call the DEPRECATED method. Therefore, the .?method syntax should be used.

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'"␤»
    }

See Also

class Cancellation

Removal of a task from a Scheduler before normal completion

class Channel

Thread-safe queue for sending values from producers to consumers

class CompUnit

CompUnit

class CompUnit::Repository::FileSystem

CompUnit::Repository::FileSystem

class CompUnit::Repository::Installation

CompUnit::Repository::Installation

class Distro

Distribution related information

class Grammar

Formal grammar made up of named regexes

class IO::ArgFiles

Iterate over contents of files specified on command line

class IO::CatHandle

Use multiple IO handles as if they were one

class IO::Handle

Opened file or stream

class IO::Notification

Asynchronous notification for file and directory changes

class IO::Notification::Change

Changes in a file, produced by watch-file

class IO::Path

File or directory path

class IO::Path::Cygwin

IO::Path pre-loaded with IO::Spec::Cygwin

class IO::Path::Parts

IO::Path parts encapsulation

class IO::Path::QNX

IO::Path pre-loaded with IO::Spec::QNX

class IO::Path::Unix

IO::Path pre-loaded with IO::Spec::Unix

class IO::Path::Win32

IO::Path pre-loaded with IO::Spec::Win32

class IO::Pipe

Buffered inter-process string or binary stream

class IO::Socket::Async

Asynchronous socket in TCP or UDP

class IO::Socket::Async::ListenSocket

A tap for listening TCP sockets

class IO::Socket::INET

TCP Socket

class IO::Spec

Platform specific operations on file and directory paths

class IO::Spec::Cygwin

Platform specific operations on file and directory paths for Cygwin

class IO::Spec::QNX

Platform specific operations on file and directory paths QNX

class IO::Spec::Unix

Platform specific operations on file and directory paths for POSIX

class IO::Spec::Win32

Platform specific operations on file and directory paths for Windows

class IO::Special

Path to special I/O device

class Kernel

Kernel related information

class Lock

A low-level, re-entrant, mutual exclusion lock

class Lock::ConditionVariable

Condition variables used in locks

class Match

Result of a successful regex match

class Pod::Block

Block in a Pod document

class Pod::Block::Code

Verbatim code block in a Pod document

class Pod::Block::Comment

Comment in a Pod document

class Pod::Block::Declarator

Declarator block in a Pod document

class Pod::Block::Named

Named block in a Pod document

class Pod::Block::Para

Paragraph in a Pod document

class Pod::Block::Table

Table in a Pod document

class Pod::Defn

Pod definition list

class Pod::FormattingCode

Pod formatting code

class Pod::Heading

Heading in a Pod document

class Pod::Item

Item in a Pod enumeration list

class Proc

Running process (filehandle-based interface)

class Proc::Async

Running process (asynchronous interface)

class Promise

Status/result of an asynchronous computation

class Regex

String pattern

class Semaphore

Control access to shared resources by multiple threads

class Supplier

Live Supply factory

class Supplier::Preserving

Cached live Supply factory

class Supply

Asynchronous data stream with multiple subscribers

class Tap

Subscription to a Supply

class Thread

Concurrent execution of code (low-level)

class ThreadPoolScheduler

Scheduler that distributes work among a pool of threads

class Unicode

Unicode related information

class VM

Raku Virtual Machine related information

The Camelia image is copyright 2009 by Larry Wall. "Raku" is trademark of the Yet Another Society. All rights reserved.