Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Make .unique(:as) about 1.5x faster
There is little point in optimising the cases with a :with parameter, as
the bottleneck there is the use of first() to check identity.
  • Loading branch information
lizmat committed Sep 23, 2015
1 parent ddd2fe6 commit abb9712
Showing 1 changed file with 34 additions and 8 deletions.
42 changes: 34 additions & 8 deletions src/core/Any-iterable-methods.pm
Expand Up @@ -708,15 +708,41 @@ augment class Any {
};
}
multi method unique( :&as! ) {
my $seen := nqp::hash();
my str $target;
gather self.map: {
$target = &as($_).WHICH;
unless nqp::existskey($seen, $target) {
nqp::bindkey($seen, $target, 1);
take $_;
Seq.new(class :: does Iterator {
has Mu $!iter;
has &!as;
has $!seen;
method BUILD(\list, &!as) {
$!iter = as-iterable(list).iterator;
$!seen := nqp::hash();
self
}
}
method new(\list, &as) { nqp::create(self).BUILD(list, &as) }
method pull-one() {
my Mu $value;
my str $needle;
until ($value := $!iter.pull-one) =:= IterationEnd {
$needle = nqp::unbox_s(&!as($value).WHICH);
unless nqp::existskey($!seen, $needle) {
nqp::bindkey($!seen, $needle, 1);
return $value;
}
}
IterationEnd
}
method push-all($target) {
my Mu $value;
my str $needle;
until ($value := $!iter.pull-one) =:= IterationEnd {
$needle = nqp::unbox_s(&!as($value).WHICH);
unless nqp::existskey($!seen, $needle) {
nqp::bindkey($!seen, $needle, 1);
$target.push($value);
}
}
IterationEnd
}
}.new(self, &as))
}
multi method unique( :&with! ) {
nextwith() if &with === &[===]; # use optimized version
Expand Down

0 comments on commit abb9712

Please sign in to comment.