hyper <<

Documentation for hyper <<, assembled from the following types:

language documentation Operators

From Operators

(Operators) hyper <<

Hyper Operators include « and », with their ASCII variants << and >>.

Hyper operators apply a given operator enclosed by « and » to one or two lists, returning the resulting list. The pointy part of « or » has to point to the shorter list. A list with just one element is fine too. If one of the lists is shorter than the other, the operator will cycle over the shorter list until all elements of the longer list are processed.

say (123) »*» 2;          # OUTPUT: «(2 4 6)␤» 
say (1234) »~» <a b>;   # OUTPUT: «(1a 2b 3a 4b)␤» 
say (123) »+« (456);  # OUTPUT: «(5 7 9)␤» 

Assignment meta operators can be hyped.

my @a = 123;
say @a »+=» 1;    # OUTPUT: «[2 3 4]␤» 

Hyper forms of unary operators have the pointy bit point to the operator and the blunt end at the list to be operated on.

my @wisdom = TrueFalseTrue;
say !« @wisdom;     # OUTPUT: «[False True False]␤» 
 
my @a = 123;
@a»++;              # OUTPUT: «(2, 3, 4)␤» 

Hyper operators are defined recursively on nested arrays.

say -« [[12], 3]; # OUTPUT: «[[-1 -2] -3]␤» 

Also, methods can be called in an out of order, concurrent fashion. The resulting list is in order. Note that all hyper operators are candidates for autothreading and will cause tears if the methods have side effects. The optimizer has full reign over hyper operators, which is the reason that they cannot be defined by the user.

class CarefulClass { method take-care {} }
my CarefulClass @objs;
my @results = @objs».take-care();
 
my @slops;        # May Contain Nuts 
@slops».?this-method-may-not-exist();

Hyper operators can work with hashes. The pointy direction indicates if missing keys are to be ignored in the resulting hash. The enclosed operator operates on all values that have keys in both hashes.

%foo «+» %bar; intersection of keys
%foo »+« %bar; union of keys
%outer »+» %inner; only keys of %inner that exist in %outer will occur in the result
my %outer = 123 Z=> <a b c>;
my %inner = 12 Z=> <x z>;
say %outer «~» %inner;          # OUTPUT: «{"1" => "ax", "2" => "bz"}␤» 

Hyper operators can take user defined operators as its operator argument.

sub pretty-file-site (Int $size --> Str{
    # rounding version of infix:</>(Int, Int) 
    sub infix:<r/>(Int \i1Int \i2{
        round(i1 / i20.1)
    }
 
    # we build a vector of fractions of $size and zip that with the fitting prefix 
    for $size «[r/]« (2**602**502**402**302**202**10)
              Z      <EB     PB     TB     GB     MB     KB> -> [\v,\suffix{
        # starting with the biggest suffix, we take the first that is 0.5 of that suffix or bigger 
        return v ~ ' ' ~ suffix if v > 0.4
    }
    # this be smaller or equal then 0.4 KB 
    return $size.Str;
}
 
for 605040302010 -> $test {
    my &a = { (2 ** $test* (1/41/2110100).pick * (1..10).pick };
    print pretty-file-site(a.Intxx 2' ';
}
 
# OUTPUT: «10 EB 4 EB 2 PB 5 PB 0.5 PB 4 TB 300 GB 4.5 GB 50 MB 200 MB 9 KB 0.6 MB␤» 

Whether hyperoperators descend into child lists depends on the nodality of the inner operator of a chain. For the hyper method call operator (».) the nodality of the target method is significant.

say (<a b>, <c d e>.elems;        # OUTPUT: «(2 3)␤» 
say (<a b>, <c d e>.&{ .elems };  # OUTPUT: «((1 1) (1 1 1))␤» 

You can chain hyper operators to destructure a List of Lists.

my $neighbors = ((-10), (0-1), (01), (10));
my $p = (23);
say $neighbors »>>+<<» ($p*);   # OUTPUT: «((1 3) (2 2) (2 4) (3 3))␤»