Documentation for routine handles assembled from the following pages:

Language documentation: Type system §

From Type system

(Type system) trait handles §

Defined as:

multi sub trait_mod:<handles>(Attribute:D $target$thunk)

The trait handles applied to an attribute of a class will delegate all calls to the provided method name to the method with the same name of the attribute. The object referenced by the attribute must be initialized. A type constraint for the object that the call is delegated to can be provided.

class A      { method m(){ 'A::m has been called.' } }
class B is A { method m(){ 'B::m has been called.' } }
class C {
    has A $.delegate handles 'm';
    method new($delegate){ self.bless(delegate => $delegate}
};
say C.new(B.new).m(); # OUTPUT: «B::m has been called.␤»

Instead of a method name, a Pair (for renaming), a list of names or Pairs, a Regex or a Whatever can be provided. In the latter case existing methods, both in the class itself and its inheritance chain, will take precedence. If even local FALLBACKs should be searched, use a HyperWhatever.

class A {
    method m1(){ 'A::m1 has been called.' }
    method m2(){ 'A::m2 has been called.' }
}
 
class C {
    has $.delegate handles <m1 m2> = A.new()
}
say C.new.m2# OUTPUT: «A::m2 has been called.␤» 
 
class D {
    has $.delegate handles /m\d/ = A.new()
}
say D.new.m1# OUTPUT: «A::m1 has been called.␤» 
 
class E {
    has $.delegate handles (em1 => 'm1'= A.new()
}
say E.new.em1# OUTPUT: «A::m1 has been called.␤» 
 
class F {
  # Delegates all methods from A 
  has A $.delegate handles *;
}
say F.new.m1# OUTPUT: «A::m1 has been called.␤» 
say F.new.m2# OUTPUT: «A::m2 has been called.␤»

Class: IO::CatHandle §

From IO::CatHandle

(IO::CatHandle) method handles §

Defines as:

method handles(IO::CatHandle:D: --> Seq:D)

Returns a Seq containing the currently-active handle, as well as all the remaining source handles produced by calling next-handle. If the invocant has already been fully-consumed, returns an empty Seq.

This method is especially handy when working with IO::ArgFiles, where you want to treat each filehandle separately:

# print at most the first 2 lines of each file in $*ARGFILES: 
.say for flat $*ARGFILES.handles.map: *.lines: 2

It is acceptable to call this method multiple times; .handles.head is a valid idiom for obtaining the currently-active handle. If, between reification of the elements of the returned Seq the handles get switched by some other means, the next element produced by the Seq would be the next handle of the invocant, not the handle that would've been produced if no switching occurred:

(my $file1 := 'file1'.IO).spurt: "1a\n1b\n1c";
(my $file2 := 'file2'.IO).spurt: "2a\n2b\n2c";
(my $file3 := 'file3'.IO).spurt: "3a\n3b\n3c";
my $cat := IO::CatHandle.new: $file1$file2$file3;
for $cat.handles {
    say .lines: 2;
    $cat.next-handle;
}
# OUTPUT: «(1a 1b)␤(3a 3b)␤»

Likewise, reifying the returned Seq consumes the invocant's source handles and once it is fully reified the invocant becomes fully-consumed.