Last active
March 8, 2020 14:00
-
-
Save uzluisf/7f575c702373565a18b6d74565b2db40 to your computer and use it in GitHub Desktop.
Short write-up about delegation in Raku
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
=begin pod | |
X<|Delegation> | |
=head2 Delegation | |
Delegation is a technique whereby a member of an object (the I«delegatee») is | |
evaluated in the context of another original object (the I«delegator»). In other | |
words, all method calls on the delegator are I«delegated» to the delegatee. | |
In Raku, delegation is specified by applying the L«handles|/language/typesystem#trait_handles» | |
trait to an attribute. The arguments provided to the trait specify the methods | |
the current object and the delegatee object will have in common. Instead of a | |
list of method names, a C<Pair> (for renaming), a list of C<Pairs>, a C<Regex> | |
or a C<Whatever> can be provided. | |
=begin code | |
class Book { | |
has Str $.title; | |
has Str $.author; | |
has Str $.language; | |
has Cool $.publication; | |
} | |
class Product { | |
has Book $.book handles('title', 'author', 'language', year => 'publication'); | |
} | |
my $book = Book.new: | |
:title<Dune>, | |
:author('Frank Herbert'), | |
:language<English>, | |
:publication<1965> | |
; | |
given Product.new(:$book) { | |
say .title; # OUTPUT: «Dune» | |
say .author; # OUTPUT: «Frank Herbert» | |
say .language; # OUTPUT: «English» | |
say .year; # OUTPUT: «1965» | |
} | |
=end code | |
In the example above, the class C«Product» defines the attribute C«$.book» | |
and mark it with the C«handles» trait to specify the methods that will be | |
forwarded to the class C«Book» whenever they're invoked on an instance | |
object of the C«Product» class. There are a few things to notice here: | |
=item We didn't write any methods inside the C«Product» class that we invoked | |
in its instance object. Instead, we instructed the class to delegate a call to | |
any those methods to the C«Book» class. | |
=item We've specified the method names C«title», C«author», and C«language» | |
as they appear in the C«Book» class. On the othe hand, we've renamed | |
the C«publication» method to C«year» by providing the appropriate C«Pair». | |
Delegation can be used as an alternative to inheritance by delegating | |
to the parent class and not inheriting all of its methods. For example, the | |
following C«Queue» class delegates several methods proper of queues | |
to L«Array|/type/Array» while also providing a preferred interface for a few | |
of those methods (e.g., C«enqueue» for C«push»): | |
=begin code | |
class Queue { | |
has @!q handles( | |
enqueue => 'push', dequeue => 'shift', | |
'push', 'shift', 'head', 'tail', 'elems', 'splice' | |
); | |
method gist { | |
'[' ~ @!q.join(', ') ~ ']' | |
} | |
} | |
my Queue $q .= new; | |
$q.enqueue($_) for 1..5; | |
$q.push(6); | |
say $q.shift; # OUTPUT: «1» | |
say $q.dequeue while $q.elems; # OUTPUT: «23456» | |
$q.enqueue($_) for <Perl Python Raku Ruby>; | |
say $q.head; # OUTPUT: «Perl» | |
say $q.tail; # OUTPUT: «Ruby» | |
say $q; # OUTPUT: «[Perl, Python, Raku, Ruby]» | |
$q.dequeue while $q.elems; | |
say $q; # OUTPUT: «[]» | |
=end code | |
=end pod |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment