Permalink
Browse files

[sequence] is the new series

  • Loading branch information...
1 parent 885149f commit ef86bef352d19689ee4eee980ffc976fbedca9ba @moritz moritz committed Sep 24, 2010
@@ -1,7 +1,7 @@
use v6;
use Test;
-# L<S03/List infix precedence/"the series operator">
+# L<S03/List infix precedence/"the sequence operator">
plan 19;
@@ -32,7 +32,7 @@ is (1, 1, { $^a + $^b } ... 9).[^7].join(', '), '1, 1, 2, 3, 5, 8, 13', 'arity-2
is (1, 1, 2, -> $a, $b { $a + $b } ... 9).[^7].join(', '), '1, 1, 2, 3, 5, 8, 13', 'arity-2 Fibonacci, 3 seeds';
is (1, 1, 2, 3, { $^a + $^b } ... 9).[^7].join(', '), '1, 1, 2, 3, 5, 8, 13', 'arity-2 Fibonacci, 4 seeds';
-# series with slurpy functions
+# sequence with slurpy functions
{
sub nextprime( *@prev_primes ) {
@@ -16,8 +16,8 @@ plan 13;
# Test with exact limit
{
my @rolls = ({ (1..2).pick } ... 2).munch(100);
- ok +@rolls > 0, 'the series had at least one element...';
- ok +@rolls < 100, '... and the series terminated';
+ ok +@rolls > 0, 'the sequence had at least one element...';
+ ok +@rolls < 100, '... and the sequence terminated';
is @rolls.grep(Int).elems, +@rolls, 'all the rolls are Ints';
is @rolls.grep(2).elems, 1, 'There was exactly one 2 rolled...';
is @rolls[@rolls.elems - 1], 2, '...and it was the last roll';
@@ -26,7 +26,7 @@ plan 13;
# Test with limit between possible values
{
my @rolls = ({ (1..2).pick } ... 1.5).munch(100);
- ok +@rolls == 100, 'the series is infinite...';
+ ok +@rolls == 100, 'the sequence is infinite...';
is @rolls.grep(Int).elems, +@rolls, 'all the rolls are Ints';
}
View
@@ -0,0 +1,238 @@
+use v6;
+use Test;
+
+# L<S03/List infix precedence/"the sequence operator">
+
+plan 122;
+
+# single-term sequence
+
+is ~( 1 ... 1 ), '1', '1 ... 1';
+is ~( 'a' ... 'a' ), 'a', "'a' ... 'a'";
+
+# finite sequence that exactly hit their limit
+
+is (1 ... 5).join(', '), '1, 2, 3, 4, 5', 'simple sequence with one item on the LHS';
+is (1 ... -3).join(', '), '1, 0, -1, -2, -3', 'simple decreasing sequence with one item on the LHS';
+is (1, 3 ... 9).join(', '), '1, 3, 5, 7, 9', 'simple additive sequence with two items on the LHS';
+is (1, 0 ... -3).join(', '), '1, 0, -1, -2, -3', 'simple decreasing additive sequence with two items on the LHS';
+is (1, 3, 5 ... 9).join(', '), '1, 3, 5, 7, 9', 'simple additive sequence with three items on the LHS';
+is (1, 3, 9 ... 81).join(', '), '1, 3, 9, 27, 81', 'simple multiplicative sequence with three items on the LHS';
+is (81, 27, 9 ... 1).join(', '), '81, 27, 9, 3, 1', 'decreasing multiplicative sequence with three items on the LHS';
+is (1, { $_ + 2 } ... 9).join(', '), '1, 3, 5, 7, 9', 'simple sequence with one item and block closure on the LHS';
+is (1, *+2 ... 9).join(', '), '1, 3, 5, 7, 9', 'simple sequence with one item and * closure on the LHS';
+is (1, { $_ - 2 } ... -7).join(', '), '1, -1, -3, -5, -7', 'simple sequence with one item and closure on the LHS';
+is (1, 3, 5, { $_ + 2 } ... 13).join(', '), '1, 3, 5, 7, 9, 11, 13', 'simple sequence with three items and block closure on the LHS';
+
+is (1, { 1 / ((1 / $_) + 1) } ... 1/5).map({.perl}).join(', '), '1, 1/2, 1/3, 1/4, 1/5', 'tricky sequence with one item and closure on the LHS';
+is (1, { -$_ } ... 1).join(', '), '1', 'simple alternating sequence with one item and closure on the LHS';
+is (1, { -$_ } ... 3).[^5].join(', '), '1, -1, 1, -1, 1', 'simple alternating sequence with one item and closure on the LHS';
+
+is ({ 3+2; } ... *).[^5].join(', '), '5, 5, 5, 5, 5', 'sequence with one scalar containing Code on the LHS';
+
+is (1 ... 5, 6, 7).join(', '), '1, 2, 3, 4, 5, 6, 7', 'simple sequence with two further terms on the RHS';
+is (1 ... 5, 4, 3).join(', '), '1, 2, 3, 4, 5, 4, 3', 'simple sequence with two extra terms on the RHS';
+is (1 ... 5, 'xyzzy', 'plugh').join(', '), '1, 2, 3, 4, 5, xyzzy, plugh', 'simple sequence with two weird items on the RHS';
+
+# infinite sequence that go past their limit
+{
+is (1 ... 5.5).munch(6).join(', '), '1, 2, 3, 4, 5, 6', 'simple sequence with one item on the LHS';
+is (1 ... -3.5).munch(6).join(', '), '1, 0, -1, -2, -3, -4', 'simple decreasing sequence with one item on the LHS';
+is (1, 3 ... 10).munch(6).join(', '), '1, 3, 5, 7, 9, 11', 'simple additive sequence with two items on the LHS';
+is (1, 0 ... -3.5).munch(6).join(', '), '1, 0, -1, -2, -3, -4', 'simple decreasing additive sequence with two items on the LHS';
+is (1, 3, 5 ... 10).munch(6).join(', '), '1, 3, 5, 7, 9, 11', 'simple additive sequence with three items on the LHS';
+is (1, 3, 9 ... 100).munch(6).join(', '), '1, 3, 9, 27, 81, 243', 'simple multiplicative sequence with three items on the LHS';
+is (81, 27, 9 ... 8/9).munch(6), (81, 27, 9, 3, 1, 1/3), 'decreasing multiplicative sequence with three items on the LHS';
+is (1, { $_ + 2 } ... 10).munch(6).join(', '), '1, 3, 5, 7, 9, 11', 'simple sequence with one item and block closure on the LHS';
+is (1, *+2 ... 10).munch(6).join(', '), '1, 3, 5, 7, 9, 11', 'simple sequence with one item and * closure on the LHS';
+is (1, { $_ - 2 } ... -8).munch(6).join(', '), '1, -1, -3, -5, -7, -9', 'simple sequence with one item and closure on the LHS';
+is (1, 3, 5, { $_ + 2 } ... 14).munch(8).join(', '), '1, 3, 5, 7, 9, 11, 13, 15', 'simple sequence with three items and block closure on the LHS';
+
+is (1, { 1 / ((1 / $_) + 1) } ... 11/60).munch(6).map({.perl}).join(', '), '1, 1/2, 1/3, 1/4, 1/5, 1/6', 'tricky sequence with one item and closure on the LHS';
+is (1, { -$_ } ... 0).munch(4).join(', '), '1, -1, 1, -1', 'simple alternating sequence with one item and closure on the LHS';
+
+is (1 ... 5.5, 6, 7).[^8].join(', '), '1, 2, 3, 4, 5, 6, 7, 8', 'simple sequence with two further terms on the RHS';
+is (1 ... 5.5, 4, 3).[^8].join(', '), '1, 2, 3, 4, 5, 6, 7, 8', 'simple sequence with two extra terms on the RHS';
+is (1 ... 5.5, 'xyzzy', 'plugh').[^8].join(', '), '1, 2, 3, 4, 5, 6, 7, 8', 'simple sequence with two weird items on the RHS';
+}
+# infinite sequence without limits
+
+is (1 ... *).[^5].join(', '), '1, 2, 3, 4, 5', 'simple sequence with one item on the LHS';
+is (1, 3 ... *).[^5].join(', '), '1, 3, 5, 7, 9', 'simple additive sequence with two items on the LHS';
+is (1, 0 ... *).[^5].join(', '), '1, 0, -1, -2, -3', 'simple decreasing additive sequence with two items on the LHS';
+is (1, 3, 5 ... *).[^5].join(', '), '1, 3, 5, 7, 9', 'simple additive sequence with three items on the LHS';
+is (8, 7, 6 ... *).[^5].join(', '), '8, 7, 6, 5, 4', 'simple decreasing additive sequence with three items on the LHS';
+is (1, 3, 9 ... *).[^5].join(', '), '1, 3, 9, 27, 81', 'simple multiplicative sequence with three items on the LHS';
+is (81, 27, 9 ... *).[^5].join(', '), '81, 27, 9, 3, 1', 'decreasing multiplicative sequence with three items on the LHS';
+is (1, { $_ + 2 } ... *).[^5].join(', '), '1, 3, 5, 7, 9', 'simple sequence with one item and block closure on the LHS';
+is (1, *+2 ... *).[^5].join(', '), '1, 3, 5, 7, 9', 'simple sequence with one item and * closure on the LHS';
+is (1, { $_ - 2 } ... *).[^5].join(', '), '1, -1, -3, -5, -7', 'simple sequence with one item and closure on the LHS';
+is (1, 3, 5, { $_ + 2 } ... *).[^7].join(', '), '1, 3, 5, 7, 9, 11, 13', 'simple sequence with three items and block closure on the LHS';
+
+is (1, { 1 / ((1 / $_) + 1) } ... *).[^5].map({.perl}).join(', '), '1, 1/2, 1/3, 1/4, 1/5', 'tricky sequence with one item and closure on the LHS';
+is (1, { -$_ } ... *).[^5].join(', '), '1, -1, 1, -1, 1', 'simple alternating sequence with one item and closure on the LHS';
+
+is (1 ... *, 6, 7).[^7].join(', '), '1, 2, 3, 4, 5, 6, 7', 'simple sequence with two further terms on the RHS';
+is (1 ... *, 4, 3).[^7].join(', '), '1, 2, 3, 4, 5, 6, 7', 'simple sequence with two extra terms on the RHS';
+is (1 ... *, 'xyzzy', 'plugh').[^7].join(', '), '1, 2, 3, 4, 5, 6, 7', 'simple sequence with two weird items on the RHS';
+
+# constant sequence
+
+is ('c', { $_ } ... *).[^10].join(', '), 'c, c, c, c, c, c, c, c, c, c', 'constant sequence started with letter and identity closure';
+is ('c', 'c' ... *).[^10].join(', '), 'c, c, c, c, c, c, c, c, c, c', 'constant sequence started with two letters';
+is ('c', 'c', 'c' ... *).[^10].join(', '), 'c, c, c, c, c, c, c, c, c, c', 'constant sequence started with three letters';
+is (1, 1 ... *).[^10].join(', '), '1, 1, 1, 1, 1, 1, 1, 1, 1, 1', 'constant sequence started with two numbers';
+is (1, 1, 1 ... *).[^10].join(', '), '1, 1, 1, 1, 1, 1, 1, 1, 1, 1', 'constant sequence started with three numbers';
+
+# misleading starts
+
+is (1, 1, 1, 2, 3 ... 10).[^10].join(', '), '1, 1, 1, 2, 3, 4, 5, 6, 7, 8', 'sequence started with three identical numbers, but then goes arithmetic';
+is (1, 1, 1, 2, 4 ... 16).join(', '), '1, 1, 1, 2, 4, 8, 16', 'sequence started with three identical numbers, but then goes geometric';
+is (4, 2, 1, 2, 4 ... 16).join(', '), '4, 2, 1, 2, 4, 8, 16', 'geometric sequence started in one direction and continues in the other';
+
+# some tests taken from Spec
+
+is (False, &prefix:<!> ... *).[^6].join(', '), (False, True, False, True, False, True).join(', '), "alternating False and True";
+is (False, &prefix:<!> ... *).[^10].grep(Bool).elems, 10, "alternating False and True is always Bool";
+is (1,2,&[+] ... 8).join(', ') , "1, 2, 3, 5, 8" , "Using &[+] works";
+is (False, { !$_ } ... *).[^6].join(', '), (False, True, False, True, False, True).join(', '), "alternating False and True";
+is (False, { !$_ } ... *).[^10].grep(Bool).elems, 10, "alternating False and True is always Bool";
+
+# L<S03/List infix precedence/'"asymptotically approaching" is not the same as "equals"'>
+# infinite sequence with limits
+
+is ~(1, 1/2, 1/4 ... 0).[^5].map({.perl}), '1 1/2 1/4 1/8 1/16', 'geometric sequence that never reaches its limit';
+is ~(1, -1/2, 1/4 ... 0).[^5].map({.perl}), '1 -1/2 1/4 -1/8 1/16', 'alternating geometric sequence that never reaches its limit';
+is (1, { 1 / ((1 / $_) + 1) } ... 0).[^5].map({.perl}).join(', '), '1, 1/2, 1/3, 1/4, 1/5', '"harmonic" sequence that never reaches its limit';
+
+# empty sequence
+
+# L<S03/List infix precedence/'limit value is on the "wrong"'>
+{
+is (1, 2 ... 0).munch(3), (1,2,3), 'No more: limit value is on the wrong side';
+}
+
+# L<S03/List infix precedence/excludes the limit if it happens to match exactly>
+# excluded limits via "...^"
+{
+ is (1 ...^ 5).join(', '), '1, 2, 3, 4', 'exclusive sequence';
+ is (1 ...^ -3).join(', '), '1, 0, -1, -2', 'exclusive decreasing sequence';
+ is (1 ...^ 5.5).munch(6).join(', '), '1, 2, 3, 4, 5, 6', "exclusive sequence that couldn't hit its limit anyway";
+ is (1, 3, 9 ...^ 81).join(', '), '1, 3, 9, 27', 'exclusive geometric sequence';
+ is (81, 27, 9 ...^ 2).munch(5).join(', '), '81, 27, 9, 3, 1', "exclusive decreasing geometric sequence that couldn't hit its limit anyway";
+ is (2, -4, 8 ...^ 32).join(', '), '2, -4, 8, -16', 'exclusive alternating geometric sequence';
+ is (2, -4, 8 ...^ -32).munch(6).join(', '), '2, -4, 8, -16, 32, -64', 'exclusive alternating geometric sequence (not an exact match)';
+ is (1, { $_ + 2 } ...^ 9).join(', '), '1, 3, 5, 7', 'exclusive sequence with closure';
+ is (1 ...^ 1), (), 'empty exclusive sequence';
+ is (1, 1 ...^ 1), (), 'empty exclusive constant sequence';
+ is (1, 2 ...^ 0).munch(3), (1, 2, 3), 'empty exclusive arithmetic sequence';
+ is (1, 2 ...^ 0, 'xyzzy', 'plugh').[^3].join(', '), '1, 2, 3', 'exclusive sequence empty but for extra items';
+ is ~(1 ...^ 0), '1', 'singleton exclusive sequence';
+ is (4...^5).join(', '), '4', '4...^5 should parse as 4 ...^ 5 and not 4 ... ^5';
+}
+
+
+# RT #75698
+ok ?(one((-5 ... ^5).flat) == 0), '-5 ... ^5 produces just one zero';
+
+# RT #75316
+isa_ok (1...()), Failure,
+ 'empty list on right side of sequence operator does not cause infinite loop';
+
+# RT #73508
+is (1,2,4...*)[10], 1024,
+ 'element from list generated using infinite sequence is accessible by index';
+
+# RT #72914
+is (4 ... ^5).join(', '), '4, 3, 2, 1, 0, 1, 2, 3, 4',
+ 'geometric sequence started in one direction and continues in the other with exclusion';
+
+lives_ok { (1 ... 5).perl }, 'Can take .perl of sequence';
+is eval((1 ... 5).perl).join(','), '1,2,3,4,5',
+ 'eval($sequence.perl) reproduces result list';
+
+is ~((1 ... *) Z~ ('a' ... 'z')).munch(5), "1a 2b 3c 4d 5e", "Zipping two sequence in parallel";
+
+{
+ is (1, 2, 4 ... 3).munch(4), (1, 2, 4, 8), "sequence that does not hit the limit";
+ is (1, 2, 4 ... 2), (1, 2), "sequence that aborts during LHS";
+
+ is (1, 2, 4 ... 1.5).munch(4), (1,2,4,8), "sequence that does not hit the limit";
+ is (1, 2, 4 ... 1), (1), "sequence that aborts during LHS";
+
+ is ~(1, -2, 4 ... 1), '1', 'geometric sequence with smaller RHS and sign change';
+ is ~(1, -2, 4 ... 2).munch(4), '1 -2 4 -8', 'geometric sequence with smaller RHS and sign change';
+ is ~(1, -2, 4 ... 3).munch(4), '1 -2 4 -8', 'geometric sequence with smaller RHS and sign change';
+ is ~(1, -2, 4 ... 25).munch(10), '1 -2 4 -8 16 -32 64 -128 256 -512', 'geometric sequence with sign-change and non-matching end point';
+
+ is (1, 2, 4, 5, 6 ... 2), (1, 2), "sequence that aborts during LHS, before actual calculations kick in";
+
+ is (1, 2, 4, 5, 6 ... 3).munch(6), (1,2,4,5,6,7), "sequence that aborts during LHS, before actual calculations kick in";
+}
+
+# tests for the types returned
+
+{
+ my @a = 1, 2, 3 ... 100;
+ is @a.elems, 100, "1, 2, 3 ... 100 generates a sequence with one hundred elements...";
+ is @a.grep(Int).elems, 100, "... all of which are Ints";
+}
+
+{
+ my @a = 1.Rat, 2.Rat, 3.Rat ... 100;
+ is @a.elems, 100, "1.Rat, 2.Rat, 3.Rat ... 100 generates a sequence with one hundred elements...";
+ is @a.grep(Rat).elems, 100, "... all of which are Rats";
+}
+
+{
+ my @a = 1.Num, 2.Num, 3.Num ... 100;
+ is @a.elems, 100, "1.Num, 2.Num, 3.Num ... 100 generates a sequence with one hundred elements...";
+ is @a.grep(Num).elems, 100, "... all of which are Nums";
+}
+
+{
+ my @a = 1, 2, 4 ... 64;
+ is @a.elems, 7, "1, 2, 4 ... 64 generates a sequence with seven elements...";
+ is @a.grep(Int).elems, @a.elems, "... all of which are Ints";
+}
+
+{
+ my @a = 1.Rat, 2.Rat, 4.Rat ... 64;
+ is @a.elems, 7, "1.Rat, 2.Rat, 4.Rat ... 64 generates a sequence with seven elements...";
+ is @a.grep(Rat).elems, 7, "... all of which are Rats";
+}
+
+{
+ my @a = 1.Num, 2.Num, 4.Num ... 64;
+ is @a.elems, 7, "1.Num, 2.Num, 4.Num ... 64 generates a sequence with seven elements...";
+ is @a.grep(Num).elems, 7, "... all of which are Nums";
+}
+
+# RT #74606
+is (1, +* ... *).[^5].join('|'), (1 xx 5).join('|'),
+ '1, +* works for sequence';
+
+# RT #75768
+is ~(1...10)[2...4], '3 4 5', 'can index sequence with sequence';
+
+{
+ is (1, 2 ... *>=5), (1,2,3,4,5), "sequence with code on the rhs";
+ is (1, 2 ... *>5), (1,2,3,4,5,6), "sequence with code on the rhs";
+ is (1, 2 ...^ *>=5), (1,2,3,4), "exclusive sequence with code on the rhs";
+ is (1, 2 ...^ *>5), (1,2,3,4,5), "exclusive sequence with code on the rhs";
+}
+
+is (1, 2 , {last if $_>=5; $_+1} ... *), (1,2,3,4,5), "sequence that lasts in the last item of lhs";
+
+{
+ is (1..* ... 5), (1, 2, 3, 4, 5), '1..* ... 5';
+ my @fib := (0, 1, *+* ... * );
+ is (@fib ... 8), (0 , 1, 1, 2 , 3, 5, 8), '@fib ... 8';
+}
+
+# RT #75828
+eval_dies_ok '1, 2, 3, ... 5', 'comma before sequence operator is caught';
+
+done_testing;
+
+# vim: ft=perl6
Oops, something went wrong.

0 comments on commit ef86bef

Please sign in to comment.