Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Tree: 39024d8051
Fetching contributors…

Cannot retrieve contributors at this time

887 lines (820 sloc) 29.247 kB
my class Bag { ... }
my class KeyBag { ... }
my class KeySet { ... }
my class MapIter { ... }
my class Pair { ... }
my class Range { ... }
my class Set { ... }
my class X::Bind::Slice { ... }
my class X::Bind::ZenSlice { ... }
my class Any { # declared in BOOTSTRAP
# my class Any is Mu {
my $default= []; # so that we can check passing of parameters to ".hash"
multi method ACCEPTS(Any:D: Mu \a) { self === a }
########
# List-like methods for Any.
########
# primitives
method infinite() { Nil }
method exists(Any:U: $key) { False }
method delete(Any:U: $key) { Nil }
method list() {
nqp::p6list(
self.DEFINITE ?? nqp::list(self) !! nqp::list(), List, Mu
);
}
method flat() {
nqp::p6list(
self.DEFINITE ?? nqp::list(self) !! nqp::list(), List, Bool::True
);
}
method eager() {
nqp::p6list(
self.DEFINITE ?? nqp::list(self) !! nqp::list(), List, Bool::True
).eager;
}
method hash() {
my % = self.DEFINITE ?? self !! ();
}
# derived from .list
method elems() { self.list.elems }
method end() { self.list.end }
method uniq(|c) { self.list.uniq(|c) }
method squish(|c) { self.list.squish(|c) }
method pick($n = 1) { self.list.pick($n) }
method roll($n = 1) { self.list.roll($n) }
method reverse() { self.list.reverse }
method sort($by = &infix:<cmp>) { self.list.sort($by) }
method values() { self.list }
method keys() { self.list.keys }
method kv() { self.list.kv }
method pairs() { self.list.pairs }
method reduce(&with) { self.list.reduce(&with) }
proto method classify(|) { * }
multi method classify($test) {
{}.classify-list( $test, self.list );
}
multi method classify($test, :$into!) {
( $into // $into.new ).classify-list( $test, self.list );
}
proto method categorize(|) { * }
multi method categorize($test) {
{}.categorize-list( $test, self.list );
}
multi method categorize($test, :$into!) {
( $into // $into.new ).categorize-list( $test, self.list );
}
# derived from MapIter/list
method lol() {
MapIter.new(self.list, { .item }, Mu).list
}
method map($block) is rw {
MapIter.new(self, $block, Bool::True).list
}
proto method tree(|) { * }
multi method tree(Any:U:) { self }
multi method tree(Any:D:) { self.lol }
multi method tree(Any:D: Cool $count as Int) {
$count > 1
?? MapIter.new(self.list, { .tree($count-1).item }, Mu).list
!! $count == 1
?? self.lol
!! self
}
multi method tree(Any:D: &c) {
MapIter.new(self.list, { .&c.item }, Mu).list
}
method Array() { Array.new(self.flat) }
# auto-vivifying
proto method push(|) { * }
multi method push(Any:U \SELF: *@values) {
&infix:<=>(SELF, Array.new);
SELF.push(@values);
}
proto method unshift(|) { * }
multi method unshift(Any:U \SELF: *@values) {
&infix:<=>(SELF, Array.new);
SELF.unshift(@values);
}
method grep(Mu $test) is rw {
self.map({ $_ if $_ ~~ $test });
}
method first(Mu $test) is rw {
my @results := self.grep($test);
@results ?? @results[0] !! Nil;
}
method join($separator = '') {
my $list = (self,).flat.eager;
my Mu $rsa := nqp::list_s();
$list.gimme(4); # force reification of at least 4 elements
unless $list.infinite { # presize array
nqp::setelems($rsa, nqp::unbox_i($list.elems));
nqp::setelems($rsa, 0);
}
my $tmp;
while $list.gimme(0) {
$tmp := $list.shift;
nqp::push_s($rsa,
nqp::unbox_s(nqp::istype($tmp, Str) ?? $tmp !! $tmp.Str));
}
nqp::push_s($rsa, '...') if $list.infinite;
nqp::p6box_s(nqp::join(nqp::unbox_s($separator.Str), $rsa))
}
method min($by = &infix:<cmp>) {
my $cmp = $by.arity == 2 ?? $by !! { $by($^a) cmp $by($^b) }
my $min;
for self {
$min = $_ if .defined and !$min.defined || $cmp($_, $min) < 0;
}
$min // +$Inf;
}
method max($by = &infix:<cmp>) {
my $cmp = $by.arity == 2 ?? $by !! { $by($^a) cmp $by($^b) }
my $max;
for self {
$max = $_ if .defined and !$max.defined || $cmp($_, $max) > 0;
}
$max // -$Inf;
}
method minmax($by = &infix:<cmp>) {
my $cmp = $by.arity == 2 ?? $by !! { $by($^a) cmp $by($^b) };
my $min;
my $max;
my $excludes_min = Bool::False;
my $excludes_max = Bool::False;
for @.list {
.defined or next;
if .isa(Range) {
if !$min.defined || $cmp($_.min, $min) < 0 {
$min = $_;
$excludes_min = $_.excludes_min;
}
if !$max.defined || $cmp($_.max, $max) > 0 {
$max = $_;
$excludes_max = $_.excludes_max;
}
} else {
if !$min.defined || $cmp($_, $min) < 0 {
$min = $_;
$excludes_min = Bool::False;
}
if !$max.defined || $cmp($_, $max) > 0 {
$max = $_;
$excludes_max = Bool::False;
}
}
}
Range.new($min // +$Inf,
$max // -$Inf,
:excludes_min($excludes_min),
:excludes_max($excludes_max));
}
# []
sub RWPAIR(\k, \v) {
my \p := nqp::create(Pair);
nqp::bindattr(p, Enum, '$!key', k);
nqp::bindattr(p, Enum, '$!value', v);
p
}
proto method postcircumfix:<[ ]>(|) { * }
multi method postcircumfix:<[ ]>() { self.list }
multi method postcircumfix:<[ ]>(:$kv!) { self.kv }
multi method postcircumfix:<[ ]>(:$p!) { self.pairs }
multi method postcircumfix:<[ ]>(:$k!) { self.keys }
multi method postcircumfix:<[ ]>(:$BIND!) {
X::Bind::ZenSlice.new(type => self.WHAT).throw
}
# @a[$x]
multi method postcircumfix:<[ ]>(\SELF: $pos) is rw {
fail "Cannot use negative index $pos on {SELF.WHAT.perl}" if $pos < 0;
SELF.at_pos($pos);
}
multi method postcircumfix:<[ ]>($pos, Mu :$BIND! is parcel) is rw {
fail "Cannot use negative index $pos on {self.WHAT.perl}" if $pos < 0;
self.bind_pos($pos, $BIND);
}
multi method postcircumfix:<[ ]>($pos, :$kv!) is rw {
fail "Cannot use negative index $pos on {self.WHAT.perl}" if $pos < 0;
$kv & !self.exists($pos) ?? () !! ($pos, self.at_pos($pos));
}
multi method postcircumfix:<[ ]>($pos, :$p!) is rw {
fail "Cannot use negative index $pos on {self.WHAT.perl}" if $pos < 0;
$p & !self.exists($pos) ?? () !! RWPAIR($pos, self.at_pos($pos));
}
multi method postcircumfix:<[ ]>($pos, :$k!) is rw {
fail "Cannot use negative index $pos on {self.WHAT.perl}" if $pos < 0;
$k & !self.exists($pos) ?? () !! $pos;
}
multi method postcircumfix:<[ ]>($pos, :$v!) is rw {
fail "Cannot use negative index $pos on {self.WHAT.perl}" if $pos < 0;
$v & !self.exists($pos) ?? () !! self.at_pos($pos);
}
# @a[1]
multi method postcircumfix:<[ ]>(\SELF: int $pos) is rw {
fail "Cannot use negative index $pos on {SELF.WHAT.perl}" if $pos < 0;
SELF.at_pos($pos);
}
multi method postcircumfix:<[ ]>(int $pos, Mu :$BIND! is parcel) is rw {
fail "Cannot use negative index $pos on {self.WHAT.perl}" if $pos < 0;
self.bind_pos($pos, $BIND);
}
multi method postcircumfix:<[ ]>(int $pos, :$kv!) is rw {
fail "Cannot use negative index $pos on {self.WHAT.perl}" if $pos < 0;
$kv & !self.exists($pos) ?? () !! ($pos, self.at_pos($pos));
}
multi method postcircumfix:<[ ]>(int $pos, :$p!) is rw {
fail "Cannot use negative index $pos on {self.WHAT.perl}" if $pos < 0;
$p & !self.exists($pos) ?? () !! RWPAIR($pos, self.at_pos($pos));
}
multi method postcircumfix:<[ ]>(int $pos, :$k!) is rw {
fail "Cannot use negative index $pos on {self.WHAT.perl}" if $pos < 0;
$k & !self.exists($pos) ?? () !! $pos;
}
multi method postcircumfix:<[ ]>(int $pos, :$v!) is rw {
fail "Cannot use negative index $pos on {self.WHAT.perl}" if $pos < 0;
$v & !self.exists($pos) ?? () !! self.at_pos($pos);
}
# @a[@i]
multi method postcircumfix:<[ ]>(\SELF: Positional \pos) is rw {
if nqp::iscont(pos) {
SELF.at_pos(pos);
}
else {
my $positions = pos.flat;
$positions.gimme(*);
if $positions.infinite {
my $list = SELF.list;
$positions.map( {
last if $_ >= $list.gimme($_ + 1);
SELF[$_];
} ).eager.Parcel;
}
else {
$positions.map( { SELF[$_] } ).eager.Parcel;
}
}
}
multi method postcircumfix:<[ ]>(Positional $pos, :$BIND!) is rw {
X::Bind::Slice.new(type => self.WHAT).throw;
}
multi method postcircumfix:<[ ]>(\SELF: Positional \pos, :$kv!) is rw {
if nqp::iscont(pos) {
SELF[pos]:$kv;
}
else {
my $positions = pos.flat;
$positions.gimme(*);
if $positions.infinite {
my $list = SELF.list;
$positions.map( {
last if $_ >= $list.gimme($_ + 1);
SELF[$_]:$kv;
} ).eager.Parcel;
}
else {
$positions.map( { SELF[$_]:$kv } ).eager.Parcel;
}
}
}
multi method postcircumfix:<[ ]>(\SELF: Positional \pos, :$p!) is rw {
if nqp::iscont(pos) {
SELF[pos]:$p;
}
else {
my $positions = pos.flat;
$positions.gimme(*);
if $positions.infinite {
my $list = SELF.list;
$positions.map( {
last if $_ >= $list.gimme($_ + 1);
SELF[$_]:$p;
} ).eager.Parcel;
}
else {
$positions.map( { SELF[$_]:$p } ).eager.Parcel;
}
}
}
multi method postcircumfix:<[ ]>(\SELF: Positional \pos, :$k!) is rw {
if nqp::iscont(pos) {
SELF[pos]:$k;
}
else {
my $positions = pos.flat;
$positions.gimme(*);
if $positions.infinite {
my $list = SELF.list;
$positions.map( {
last if $_ >= $list.gimme($_ + 1);
SELF[$_]:$k;
} ).eager.Parcel;
}
else {
$positions.map( { SELF[$_]:$k } ).eager.Parcel;
}
}
}
multi method postcircumfix:<[ ]>(\SELF: Positional \pos, :$v!) is rw {
if nqp::iscont(pos) {
SELF[pos]:$v;
}
else {
my $positions = pos.flat;
$positions.gimme(*);
if $positions.infinite {
my $list = SELF.list;
$positions.map( {
last if $_ >= $list.gimme($_ + 1);
SELF[$_]:$v;
} ).eager.Parcel;
}
else {
$positions.map( { SELF[$_]:$v } ).eager.Parcel;
}
}
}
# @a[->{}]
multi method postcircumfix:<[ ]>(\SELF: Callable $block) is rw {
SELF[$block(|(SELF.elems xx $block.count))]
}
multi method postcircumfix:<[ ]>(Callable $block, :$BIND!) is rw {
X::Bind::Slice.new(type => self.WHAT).throw;
}
multi method postcircumfix:<[ ]>(\SELF: Callable $block, :$kv!) is rw {
SELF[$block(|(SELF.elems xx $block.count))]:$kv
}
multi method postcircumfix:<[ ]>(\SELF: Callable $block, :$p!) is rw {
SELF[$block(|(SELF.elems xx $block.count))]:$p
}
multi method postcircumfix:<[ ]>(\SELF: Callable $block, :$k!) is rw {
SELF[$block(|(SELF.elems xx $block.count))]:$k
}
multi method postcircumfix:<[ ]>(\SELF: Callable $block, :$v!) is rw {
SELF[$block(|(SELF.elems xx $block.count))]:$v
}
# @a[*]
multi method postcircumfix:<[ ]>(\SELF: Whatever) is rw {
SELF[^SELF.elems]
}
multi method postcircumfix:<[ ]>(Whatever, :$BIND!) is rw {
X::Bind::Slice.new(type => self.WHAT).throw;
}
multi method postcircumfix:<[ ]>(\SELF: Whatever, :$kv!) is rw {
SELF[^SELF.elems]:$kv
}
multi method postcircumfix:<[ ]>(\SELF: Whatever, :$p!) is rw {
SELF[^SELF.elems]:$p
}
multi method postcircumfix:<[ ]>(\SELF: Whatever, :$k!) is rw {
SELF[^SELF.elems]:$k
}
multi method postcircumfix:<[ ]>(\SELF: Whatever, :$v!) is rw {
SELF[^SELF.elems]:$v
}
proto method at_pos(|) {*}
multi method at_pos(Any:D: $pos) {
fail X::OutOfRange.new(
what => 'Index',
got => $pos,
range => (0..0)
) if $pos != 0;
self;
}
multi method at_pos(Any:U \SELF: $pos) is rw {
nqp::bindattr(my $v, Scalar, '$!whence',
-> { SELF.defined || &infix:<=>(SELF, Array.new);
SELF.bind_pos($pos, $v) });
$v
}
method all() { all(self.list) }
method any() { any(self.list) }
method one() { one(self.list) }
method none() { none(self.list) }
########
# Hash-like methods for Any.
########
proto method postcircumfix:<{ }>(|) { * }
multi method postcircumfix:<{ }>() { self }
multi method postcircumfix:<{ }>(:$kv!) { self.kv }
multi method postcircumfix:<{ }>(:$p!) { self.pairs }
multi method postcircumfix:<{ }>(:$k!) { self.keys }
multi method postcircumfix:<{ }>(:$v!) { self.values }
multi method postcircumfix:<{ }>(:$BIND!) {
X::Bind::ZenSlice.new(type => self.WHAT).throw
}
# %h<key>
multi method postcircumfix:<{ }>(\SELF: $key) is rw {
SELF.at_key($key)
}
multi method postcircumfix:<{ }>(\SELF: $key, Mu :$BIND! is parcel) is rw {
SELF.bind_key($key, $BIND)
}
multi method postcircumfix:<{ }>(
\SELF: $key,
:$delete! where so $delete,
:$exists = $default,
:$kv = $default,
:$p = $default,
:$k = $default,
:$v = $default
) is rw {
if $exists & $kv & $p & $k & $v === $default { # :delete
SELF.delete($key);
}
elsif $exists !=== $default {
my $wasthere = SELF.exists($key);
SELF.delete($key);
if $kv & $p === $default { # :delete:exists?
!( $wasthere ?^ $exists )
}
elsif $kv !=== $default { # :delete:exists?:kv?
!$kv | $wasthere ?? ( $key, !( $wasthere ?^ $exists ) ) !! ();
}
elsif $p !=== $default { # :delete:exists?:p?
!$p | $wasthere ?? RWPAIR($key, !($wasthere ?^ $exists) ) !! ();
}
}
elsif $kv !=== $default { # :delete?:kv?
!$kv | SELF.exists($key) ?? ( $key, SELF.delete($key) ) !! ();
}
elsif $p !=== $default { # :delete:p?
!$p | SELF.exists($key) ?? RWPAIR($key, SELF.delete($key)) !! ();
}
elsif $k !=== $default { # :delete:k?
!$k | SELF.exists($key) ?? ( SELF.delete($key); $key ) !! ();
}
else { # :delete:v?
!$v | SELF.exists($key) ?? SELF.delete($key) !! ();
}
}
multi method postcircumfix:<{ }>(
\SELF: $key,
:$exists!,
:$kv = $default,
:$p = $default,
:$k = $default
) is rw {
my $wasthere= SELF.exists($key);
if $kv & $p & $k === $default { # :exists?
!( $wasthere ?^ $exists )
}
elsif $kv !=== $default { # :exists?:kv?
!$kv | $wasthere ?? ( $key, !( $wasthere ?^ $exists ) ) !! ();
}
else { # :exists:p?
!$p | $wasthere ?? RWPAIR($key, !( $wasthere ?^ $exists )) !! ();
}
}
multi method postcircumfix:<{ }>(\SELF: $key, :$kv!) is rw {
!$kv | SELF.exists($key) ?? ( $key, SELF.at_key($key) ) !! ();
}
multi method postcircumfix:<{ }>(\SELF: $key, :$p!) is rw {
!$p | SELF.exists($key) ?? RWPAIR( $key, SELF.at_key($key) ) !! ();
}
multi method postcircumfix:<{ }>(\SELF: $key, :$k!) is rw {
!$k | SELF.exists($key) ?? $key !! ();
}
#there is no multi method postcircumfix:<{ }>(\SELF: $key, :$v!)
# %h<a b c>
multi method postcircumfix:<{ }>(\SELF: Positional \key) is rw {
nqp::iscont(key)
?? SELF.at_key(key)
!! key.map({ SELF{$_} }).eager.Parcel
}
multi method postcircumfix:<{ }>(Positional $key, :$BIND!) is rw {
X::Bind::Slice.new(type => self.WHAT).throw
}
multi method postcircumfix:<{ }>(
\SELF: Positional \key,
:$delete! where so $delete,
:$exists = $default,
:$kv = $default,
:$p = $default,
:$k = $default,
:$v = $default
) is rw {
if nqp::iscont(key) { # handle single key immediately
SELF{key}:$delete:$exists:$kv:$p:$k:$v;
}
elsif $exists & $kv & $p & $k & $v === $default { # :delete
key.map( { SELF.delete($_) } ).eager.Parcel;
}
elsif $exists !=== $default {
# no need to initialize every iteration of map
my $wasthere;
if $p & $kv === $default { # :delete:exists?
key.map( {
SELF.delete($_) if $wasthere = SELF.exists($_);
!( $wasthere ?^ $exists );
} ).eager.Parcel
}
elsif $kv !=== $default { # :delete:exists?:kv?
key.map( {
SELF.delete($_) if $wasthere = SELF.exists($_);
!$kv | $wasthere ?? ( $_, !( $wasthere ?^ $exists ) ) !! ()
} ).eager.Parcel
}
elsif $p !=== $default { # :delete:exists?:p?
key.map( {
SELF.delete($_) if $wasthere = SELF.exists($_);
!$p | $wasthere ?? RWPAIR($_,!($wasthere ?^ $exists)) !! ()
} ).eager.Parcel
}
}
elsif $kv !=== $default { # :delete:kv?
$kv
?? key.map( {
SELF.exists($_) ?? ( $_, SELF.delete($_) ) !! ()
} ).eager.Parcel
!! key.map( {
( $_, SELF.delete($_) )
} ).eager.Parcel;
}
elsif $p !=== $default { # :delete:p?
$p
?? key.map( {
SELF.exists($_) ?? RWPAIR($_, SELF.delete($_)) !! ()
} ).eager.Parcel
!! key.map( {
RWPAIR($_, SELF.delete($_))
} ).eager.Parcel;
}
elsif $k !=== $default { # :delete:k?
$k
?? key.map( {
SELF.exists($_) ?? ( SELF.delete($_); $_ ) !! ()
} ).eager.Parcel
!! key.map( {
SELF.delete($_); $_
} ).eager.Parcel;
}
else { # :delete:v?
$v
?? key.map( {
SELF.exists($_) ?? SELF.delete($_) !! ()
} ).eager.Parcel
!! key.map( {
SELF.delete($_)
} ).eager.Parcel;
}
}
multi method postcircumfix:<{ }>(
\SELF: Positional \key,
:$exists!,
:$kv = $default,
:$p = $default,
) is rw {
if nqp::iscont(key) { # handle single key immediately
SELF{key}:$exists:$kv:$p;
}
if $kv & $p === $default { # :exists?
key.map({ !( SELF.exists($_) ?^ $exists ) }).eager.Parcel;
}
elsif $kv !=== $default { # :exists?:kv?
$kv
?? key.map( {
SELF.exists($_) ?? ( $_, $exists ) !! ()
} ).eager.Parcel
!! key.map( {
( $_, !( SELF.exists($_) ?^ $exists ) )
} ).eager.Parcel;
}
else { # :exists:p?
$p
?? key.map( {
SELF.exists($_) ?? RWPAIR( $_, $exists ) !! ()
} ).eager.Parcel
!! key.map( {
RWPAIR( $_, !( SELF.exists($_) ?^ $exists ) )
} ).eager.Parcel;
}
}
multi method postcircumfix:<{ }>(\SELF: Positional \key, :$kv!) is rw {
if nqp::iscont(key) { # handle single key immediately
SELF{key}:$kv;
}
elsif $kv {
key.map( {
SELF.exists($_) ?? ($_, SELF.at_key($_)) !! ()
} ).eager.Parcel
}
else {
key.map( {
( $_, SELF.at_key($_) )
} ).eager.Parcel;
}
}
multi method postcircumfix:<{ }>(\SELF: Positional \key, :$p!) is rw {
if nqp::iscont(key) { # handle single key immediately
SELF{key}:$p;
}
elsif $p {
key.map( {
SELF.exists($_) ?? RWPAIR($_, SELF.at_key($_)) !! ()
} ).eager.Parcel
}
else {
key.map( {
RWPAIR( $_, SELF.at_key($_) )
} ).eager.Parcel;
}
}
multi method postcircumfix:<{ }>(\SELF: Positional \key, :$k!) is rw {
if nqp::iscont(key) { # handle single key immediately
SELF{key}:$k;
}
elsif $k {
key.map( { $_ if SELF.exists($_) } ).eager.Parcel
}
else {
key
}
}
multi method postcircumfix:<{ }>(\SELF: Positional \key, :$v!) is rw {
if nqp::iscont(key) { # handle single key immediately
SELF{key}:$v;
}
elsif $v {
key.map( { SELF.exists($_) ?? SELF.at_key($_) !! () } ).eager.Parcel
}
else {
key.map( { SELF.at_key($_) } ).eager.Parcel;
}
}
# %h{*}
multi method postcircumfix:<{ }>(\SELF: Whatever) is rw {
SELF{SELF.keys}
}
multi method postcircumfix:<{ }>(Whatever, :$BIND!) is rw {
X::Bind::Slice.new(type => self.WHAT).throw
}
multi method postcircumfix:<{ }>(
\SELF: Whatever,
:$delete! where so $delete,
:$exists = $default,
:$kv = $default,
:$p = $default,
:$k = $default,
:$v = $default
) is rw {
SELF{SELF.keys}:$delete:$exists:$kv:$p:$k:$v;
}
multi method postcircumfix:<{ }>(
\SELF: Whatever,
:$exists!,
:$kv = $default,
:$p = $default,
:$k = $default
) is rw {
SELF{SELF.keys}:$exists:$kv:$p:$k
}
multi method postcircumfix:<{ }>(\SELF: Whatever, :$kv!) is rw {
SELF.kv;
}
multi method postcircumfix:<{ }>(\SELF: Whatever, :$p!) is rw {
SELF.pairs
}
multi method postcircumfix:<{ }>(\SELF: Whatever, :$k!) is rw {
SELF.keys
}
multi method postcircumfix:<{ }>(\SELF: Whatever, :$v!) is rw {
SELF.values
}
# internals
proto method at_key(|) { * }
multi method at_key(Any:D: $key) {
fail "postcircumfix:<\{ \}> not defined for type {self.WHAT.perl}";
}
multi method at_key(Any:U \SELF: $key) is rw {
nqp::bindattr(my $v, Scalar, '$!whence',
-> { SELF.defined || &infix:<=>(SELF, Hash.new);
SELF.bind_key($key, $v) });
$v
}
proto method bind_key(|) { * }
multi method bind_key(Any:D: $key, $BIND ) {
fail "postcircumfix:<\{ \}> binding not defined for type {self.WHAT.perl}";
}
multi method bind_key(Any:U \SELF: $key, $BIND ) is rw {
&infix:<=>(SELF, Hash.new);
SELF.bind_key($key, $BIND);
$BIND
}
method FLATTENABLE_LIST() {
my $list := self.list;
nqp::findmethod($list, 'FLATTENABLE_LIST')($list);
}
method FLATTENABLE_HASH() { nqp::hash() }
method Set() {
my @keys;
for self.list() {
when Pair { @keys.push(.key) if .value }
default { @keys.push($_) }
}
Set.new(@keys);
}
method KeySet() {
my @keys;
for self.list() {
when Pair { @keys.push(.key) if .value; }
default { @keys.push($_) }
}
KeySet.new(@keys);
}
method Bag() { Bag.new-from-pairs(self.list) }
method KeyBag() { KeyBag.new-from-pairs(self.list) }
}
Metamodel::ClassHOW.exclude_parent(Any);
# builtin ops
proto infix:<===>($?, $?) is pure { * }
multi infix:<===>($a?) { Bool::True }
multi infix:<===>($a, $b) {
nqp::p6bool(nqp::iseq_s(nqp::unbox_s($a.WHICH), nqp::unbox_s($b.WHICH)))
}
proto infix:<before>($, $?) is pure { * }
multi infix:<before>($x?) { Bool::True }
multi infix:<before>(\a, \b) { (a cmp b) < 0 }
proto infix:<after>($, $?) is pure { * }
multi infix:<after>($x?) { Bool::True }
multi infix:<after>(\a, \b) { (a cmp b) > 0 }
# XXX: should really be '$a is rw' (no \) in the next four operators
proto prefix:<++>(|) { * }
multi prefix:<++>(Mu:D \a is rw) { a = a.succ }
multi prefix:<++>(Mu:U \a is rw) { a = 1 }
proto prefix:<-->(|) { * }
multi prefix:<-->(Mu:D \a is rw) { a = a.pred }
multi prefix:<-->(Mu:U \a is rw) { a = -1 }
proto postfix:<++>(|) { * }
multi postfix:<++>(Mu:D \a is rw) { my $b = a; a = a.succ; $b }
multi postfix:<++>(Mu:U \a is rw) { a = 1; 0 }
proto postfix:<-->(|) { * }
multi postfix:<-->(Mu:D \a is rw) { my $b = a; a = a.pred; $b }
multi postfix:<-->(Mu:U \a is rw) { a = -1; 0 }
# builtins
proto infix:<min>(|) is pure { * }
multi infix:<min>(*@args) { @args.min }
# XXX the multi version suffers from a multi dispatch bug
# where the mandatory named is ignored in the presence of a slurpy
#proto sub min(|) { * }
#multi sub min(*@args) { @args.min() }
#multi sub min(*@args, :&by!) { @args.min(&by) }
sub min(*@args, :&by = &infix:<cmp>) { @args.min(&by) }
proto infix:<max>(|) is pure { * }
multi infix:<max>(*@args) { @args.max }
#proto sub max(|) { * }
#multi sub max(*@args) { @args.max() }
#multi sub max(*@args, :&by!) { @args.max(&by) }
sub max(*@args, :&by = &infix:<cmp>) { @args.max(&by) }
proto infix:<minmax>(|) is pure { * }
multi infix:<minmax>(*@args) { @args.minmax }
#proto sub minmax(|) { * }
#multi sub minmax(*@args) { @args.minmax() }
#multi sub minmax(*@args, :&by!) { @args.minmax(&by) }
sub minmax(*@args, :&by = &infix:<cmp>) { @args.minmax(&by) }
proto map(|) {*}
multi map(&code, *@values) { @values.map(&code) }
proto grep(|) {*}
multi grep(Mu $test, *@values) { @values.grep($test) }
proto first(|) {*}
multi first(Mu $test, *@values) { @values.first($test) }
proto join(|) { * }
multi join($sep = '', *@values) { @values.join($sep) }
proto pick(|) { * }
multi pick($n, *@values) { @values.pick($n) }
proto roll(|) { * }
multi roll($n, *@values) { @values.roll($n) }
proto keys(|) { * }
multi keys($x) { $x.keys }
proto values(|) { * }
multi values($x) { $x.values }
proto pairs(|) { * }
multi pairs($x) { $x.pairs }
proto kv(|) { * }
multi kv($x) { $x.kv }
proto elems(|) { * }
multi elems($a) { $a.elems }
proto end(|) { * }
multi end($a) { $a.end }
proto classify(|) { * }
multi classify( $test, *@items ) { {}.classify-list( $test, @items ) }
#multi classify( $test, *@items, :$into! ) { # problem in MMD
# ( $into // $into.new).classify-list( $test, @items );
#}
proto categorize(|) { * }
multi categorize( $test, *@items ) { {}.categorize-list( $test, @items ) }
#multi categorize( $test, *@items, :$into! ) { # problem in MMD
# ( $into // $into.new).categorize-list( $test, @items );
#}
proto uniq(|) { * }
multi uniq(*@values, |c) { @values.uniq(|c) }
proto squish(|) { * }
multi squish(*@values, |c) { @values.squish(|c) }
proto sub sort(|) {*}
multi sub sort(*@values) {
@values.at_pos(0).^does(Callable)
?? do { my $cmp := @values.shift; @values.sort($cmp) }
!! @values.sort;
}
proto sub item(|) is pure { * }
multi sub item(*@a) { my $ = @a }
multi sub item(Mu $a) { $a }
Jump to Line
Something went wrong with that request. Please try again.