FAST
view release on metacpan or search on metacpan
lib/FAST/List/Gen.pm view on Meta::CPAN
sub empty () {tiegen 'Empty'}
generator Empty => sub {
curse {
FETCH => sub () { },
fsize => sub () {0},
} => shift
};
=head2 source generators
=over 4
=item range C< SIZE >
returns a generator from C< 0 > to C< SIZE - 1 >
my $range = range 10;
say $range->str; # 0 1 2 3 4 5 6 7 8 9
say $range->size; # 10
=item range C< START STOP [STEP] >
returns a generator for values from C< START > to C< STOP > by C< STEP >,
inclusive.
C< STEP > defaults to 1 but can be fractional and negative. depending on your
choice of C< STEP >, the last value returned may not always be C< STOP >.
range(0, 3, 0.4) will return (0, 0.4, 0.8, 1.2, 1.6, 2, 2.4, 2.8)
print "$_ " for @{range 0, 1, 0.1};
# 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
print "$_ " for @{range 5, 0, -1};
# 5 4 3 2 1 0
my $nums = range 0, 1_000_000, 2;
print "@$nums[10, 100, 1000]";
# gets the tenth, hundredth, and thousandth numbers in the range
# without calculating any other values
C<range> also accepts character strings instead of numbers. it will behave
the same way as perl's internal C< .. > operator, except it will be lazy.
say range('a', 'z')->str; # 'a b c d e f g ... x y z'
range('a', 'zzz', 2)->say; # 'a c e g i k m ... zzu zzw zzy'
say <A .. ZZ>->str; # 'A B C D E ... ZX ZY ZZ'
<1..>->zip(<a..>)->say(10); # '1 a 2 b 3 c 4 d 5 e'
to specify an infinite range, you can pass C< range > an infinite value
(C< 9**9**9 > works well), or the glob C< ** >, or the string C< '*' >
range(1, 9**9**9) ~~ range(1, **) ~~ range(1, '*') ~~ <1..*> ~~ <1..>
ranges only store their endpoints, and ranges of all sizes take up the same
amount of memory.
=cut
sub range ($;$$) {
splice @_, 1, 1, 9**9**9
if @_ > 1 and $_[1] eq '*'
|| \$_[1] == \**;
for (@_) {
defined
and /^[a-z]+$/i
and not looks_like_number $_
and goto &arange
}
tiegen Range => @_ == 1 ? (0, $_[0] - 1) : @_
}
generator Range => sub {
my ($class, $low, $high, $step, $size) = (@_, 1);
$size = $high < 9**9**9
? do {
$size = $step > 0 ? $high - $low : $low - $high;
$size = 1 + $size / abs $step;
$size > 0 ? int $size : 0
} : $high;
$size = 0 unless $low < 9**9**9;
curse {
FETCH => sub {
$_[1] < $size
? $low + $step * $_[1]
: croak "range index $_[1] out of bounds [0 .. @{[$size - 1]}]"
},
fsize => sub {$size},
range => sub {$low, $step, $size},
} => $class
};
{my %map; @map{0..25} = 'a'..'z';
my @cache = 'a'..'zz';
sub num2alpha {
my $num = @_ ? $_[0] : $_;
return '-'.num2alpha(-$num) if $num < 0;
return $cache[$num] if $num < 702;
my @str;
while ($num > -1) {
unshift @str, $map{$num % 26};
$num = int($num / 26) - 1;
}
join '' => @str
}}
{my %map; @map{'a'..'z'} = 0..25;
sub alpha2num {
my $str = shift;
return -alpha2num($1) if $str =~ /^-(.+)/;
my ($num, $scale);
for (split //, reverse $str) {
$num += ($map{$_} + !!$scale) * 26**$scale++
}
$num
( run in 1.020 second using v1.01-cache-2.11-cpan-39bf76dae61 )