Skip to content

Instantly share code, notes, and snippets.

@zoffixznet
Created September 4, 2016 04:54
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save zoffixznet/8ff9ec5e7bdf18166b35c6ca064ddba7 to your computer and use it in GitHub Desktop.
use MONKEY-GUTS;
my class X::Immutable { }
my class X::Range::InvalidArg { }
my class ZRange is Cool does Iterable does Positional {
has $.min;
has $.max;
has int $!excludes-min;
has int $!excludes-max;
has int $!infinite;
has int $!is-int;
method !SET-SELF( $!min, $!max, \excludes-min, \excludes-max, \infinite) {
$!excludes-min = excludes-min // 0;
$!excludes-max = excludes-max // 0;
$!infinite = infinite;
$!is-int = nqp::istype($!min,Int) && nqp::istype($!max,Int);
self
}
method is-lazy { self.infinite }
# The order of "method new" declarations matters here, to ensure
# appropriate candidate tiebreaking when mixed type arguments
# are present (e.g., Range,Whatever or Real,Range).
multi method new(Range $min, \max, :$excludes-min, :$excludes-max) {
X::Range::InvalidArg.new(:got($min)).throw;
}
multi method new(\min, Range $max, :$excludes-min, :$excludes-max) {
X::Range::InvalidArg.new(:got($max)).throw;
}
multi method new(Seq \min, \max, :$excludes-min, :$excludes-max) {
X::Range::InvalidArg.new(:got(Seq)).throw;
}
multi method new(\min , Seq \max, :$excludes-min, :$excludes-max) {
X::Range::InvalidArg.new(:got(Seq)).throw;
}
multi method new(Complex \min, \max, :$excludes-min, :$excludes-max) {
X::Range::InvalidArg.new(:got(min)).throw;
}
multi method new(\min , Complex \max, :$excludes-min, :$excludes-max) {
X::Range::InvalidArg.new(:got(max)).throw;
}
multi method new(Whatever \min,Whatever \max,:$excludes-min,:$excludes-max){
nqp::create(self)!SET-SELF(-Inf,Inf,$excludes-min,$excludes-max,1);
}
multi method new(Whatever \min, \max, :$excludes-min, :$excludes-max) {
nqp::create(self)!SET-SELF(-Inf,max,$excludes-min,$excludes-max,1);
}
multi method new(\min, Whatever \max, :$excludes-min, :$excludes-max) {
nqp::create(self)!SET-SELF(min,Inf,$excludes-min,$excludes-max,1);
}
# multi method new(Real \min, Real() $max, :$excludes-min, :$excludes-max) {
# nqp::create(self)!SET-SELF(
# min,$max,$excludes-min,$excludes-max,$max == Inf || min == -Inf);
# }
multi method new(List:D \min, \max, :$excludes-min, :$excludes-max) {
nqp::create(self)!SET-SELF(
+min,
nqp::istype(max,List) || nqp::istype(max,Match) ?? +max !! max,
$excludes-min, $excludes-max, 0);
}
multi method new(Match:D \min, \max, :$excludes-min, :$excludes-max) {
nqp::create(self)!SET-SELF(
+min,
nqp::istype(max,List) || nqp::istype(max,Match) ?? +max !! max,
$excludes-min, $excludes-max, 0);
}
multi method new(\min, \max, :$excludes-min, :$excludes-max!) {
nqp::create(self)!SET-SELF(min, max,$excludes-min,$excludes-max,0);
}
multi method new(\min, \max, :$excludes-min!, :$excludes-max) {
nqp::create(self)!SET-SELF(min,max,$excludes-min,$excludes-max,0);
}
multi method new(\min, \max) { nqp::create(self)!SET-SELF(min,max,0,0,0) }
method rand() {
fail "Can only get a random value on Real values, did you mean .pick?"
unless nqp::istype($!min,Real) && nqp::istype($!max,Real);
fail "Can only get a random value from numeric values"
if $!min === NaN || $!max === NaN;
fail "Can not get a random value from an infinite range"
if $!min === -Inf || $!max === Inf;
my $range = $!max - $!min;
fail "Can only get a random value if the range is positive"
unless $range > 0;
my $value = 0;
if $!excludes-min || $!excludes-max {
if $!excludes-min {
if $!excludes-max {
$value = $range.rand while $value == 0 || $value == $range;
}
else {
$value = $range.rand while $value == 0;
}
}
else { # $!excludes-max
$value = $range;
$value = $range.rand while $value == $range;
}
}
else {
$value = $range.rand
}
$!min + $value
}
}
dd [ $_, .^name given ZRange.new(10, "15").max ];
ZRange.new(10, "15").rand;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment