# 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

Reply via email to