Roles

Role composition is flattening with conflict detection: if two roles provide the same method, the class must resolve the conflict explicitly (by defining the method), and compile time tells you if it didn't.

Roles vs classes: classes are for managing instances; roles are for managing behavior and code reuse.

role Greeter {
    method greet { "Hello, I'm {self.name}" }       # uses a method the class must provide
}

role Serializable {
    method to-hash { self.^attributes.map({ .name.substr(2) => .get_value(self) }).Hash }
}

role Comparable {
    method compare($other) { ... }                  # stub (yada): composing classes must implement it
    method less-than($other) { self.compare($other) < 0 }
}

class Person does Greeter does Serializable does Comparable {
    has $.name;
    has $.age;
    method compare($other) { $!age <=> $other.age }
}

my $ana = Person.new(name => 'Ana', age => 30);
my $bo  = Person.new(name => 'Bo', age => 25);
say $ana.greet;                    # Hello, I'm Ana
say $ana.to-hash;                  # {age => 30, name => Ana}
say $bo.less-than($ana);           # True
say $ana ~~ Greeter;               # True
say Person.^roles;                 # ((Comparable) (Serializable) (Greeter))

# Roles with attributes
role Timestamped { has DateTime $.created = DateTime.now }

# Parametric roles
role Container[::T] {
    has T @.items;
    method add(T $item) { @!items.push($item); self }
}
class IntBox does Container[Int] { }
my $box = IntBox.new.add(1).add(2);
say 
…