# New Ticket Created by David Whipp # Please include the string: [perl #84362] # in the subject line of all future correspondence about this issue. # <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=84362 >
Attached patches add tests and implementation for sequence operator with limit-function arity > 1 (the function is assumed to be false until we have enough values to call it). The tests show how this can be used to terminate a sequence when it converges, or when a specific curvature is seen: 1, */2 ... abs(*-*) < 0.01; ## convergence: 8 values 0,1,2,1,0,1,2 ...^ { $^a-$^b > $^b-$^c }; ## curvature: 5 values 1,2 ... { @_ == 4 }; ## length: 4 values
>From 608d6c1dc96b81e0537d670d9949451c227f5708 Mon Sep 17 00:00:00 2001 From: Dave Whipp <dwh...@google.com> Date: Thu, 17 Feb 2011 12:08:45 -0800 Subject: [PATCH] tests of sequence operator with limit function having arity > 1 --- S03-sequence/limit-arity-2-or-more.t | 37 ++++++++++++++++++++++++++++++++++ 1 files changed, 37 insertions(+), 0 deletions(-) create mode 100644 S03-sequence/limit-arity-2-or-more.t diff --git a/S03-sequence/limit-arity-2-or-more.t b/S03-sequence/limit-arity-2-or-more.t new file mode 100644 index 0000000..5524ea8 --- /dev/null +++ b/S03-sequence/limit-arity-2-or-more.t @@ -0,0 +1,37 @@ +use v6; +use Test; + +# L<S03/List infix precedence/"the sequence operator"> + +plan 8; + +# sequence with a limit function of arity 2 + +is (8,*/2 ... abs(*-*) < 2).join(', '), '8, 4, 2, 1', 'arity-2 convergence limit'; +is (8,*/2 ...^ abs(*-*) < 2).join(', '), '8, 4, 2', 'arity-2 excluded convergence limit'; + +# sequence with a limit function of arity 3 + +{ + my $i = -5; + my @seq = { ++$i; $i**3-9*$i } ... { ($^a-$^b) > ($^b-$^c) }; + is @seq.join(', '), '-28, 0, 10, 8, 0, -8, -10', 'arity-3 curvature limit'; +} + +{ + my $i = -5; + my @seq = { ++$i; $i**3-9*$i } ...^ { ($^a-$^b) > ($^b-$^c) }; + is @seq.join(', '), '-28, 0, 10, 8, 0, -8', 'arity-3 excluded curvature limit'; +} + +# limit functions that limit sequence exactly at arity limit + +is (2, 1, 0.5 ... abs(*-*) < 2).join(', '), '2, 1', 'ASAP arity-2 convergence limit'; +is (2, 1, 0.5 ...^ abs(*-*) < 2).join(', '), '2', 'ASAP arity-2 excluded convergence limit'; + +# limit function that accepts any number of args + +is (1 ... { @_ eq "1 2 3" }).join(', '), '1, 2, 3', 'arity-Inf limit'; +is (1 ...^ { @_ eq "1 2 3" }).join(', '), '1, 2', 'arity-Inf excluded limit'; + +done; -- 1.7.3.1
>From de547c7c44810e1cd8d03c023cc380498bff6301 Mon Sep 17 00:00:00 2001 From: Dave Whipp <dwh...@google.com> Date: Thu, 17 Feb 2011 12:07:27 -0800 Subject: [PATCH] Sequence operator supports limit functions with arity > 1 --- src/core/operators.pm | 30 ++++++++++++++++++++++-------- 1 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/core/operators.pm b/src/core/operators.pm index c92e9f2..074db9f 100644 --- a/src/core/operators.pm +++ b/src/core/operators.pm @@ -401,16 +401,30 @@ our sub _HELPER_generate-series(@lhs, $rhs , :$exclude-limit) { my $limit = ($rhs ~~ Whatever ?? Any !! $rhs); return infinite-series(@lhs , $limit) if $rhs ~~ Whatever; #shortcut infinite series so we avoid the comparisions - fail ('Limit arity cannot be larger than 1') if $limit ~~ Code && $limit.count > 1; + #fail ('Limit arity cannot be larger than 1') if $limit ~~ Code && $limit.count > 1; my $series = infinite-series(@lhs , $limit); + gather { - while $series { - my $val = $series.shift(); - if $val ~~ $limit { - take $val unless $exclude-limit ; - last ; - }; - take $val; + if $limit ~~ Code && $limit.count > 1 { + my @limit-args; + while $series { + @limit-args.shift if @limit-args == $limit.count; + my $val = $series.shift; + @limit-args.push($val); + my $done = @limit-args >= $limit.arity && $limit(|@limit-args); + take $val unless $done && $exclude-limit; + last if $done; + } + } + else { + while $series { + my $val = $series.shift(); + if $val ~~ $limit { + take $val unless $exclude-limit ; + last ; + }; + take $val; + } } } } -- 1.7.3.1