Author: lwall
Date: 2009-09-22 03:53:43 +0200 (Tue, 22 Sep 2009)
New Revision: 28351

Modified:
   docs/Perl6/Spec/S03-operators.pod
Log:
[S03] more clarifications of autogenerated generator functions, pmichaud++


Modified: docs/Perl6/Spec/S03-operators.pod
===================================================================
--- docs/Perl6/Spec/S03-operators.pod   2009-09-21 23:28:11 UTC (rev 28350)
+++ docs/Perl6/Spec/S03-operators.pod   2009-09-22 01:53:43 UTC (rev 28351)
@@ -1779,21 +1779,57 @@
     1, 3, 5 ... *   # odd numbers
     1, 2, 4 ... *   # powers of 2
 
-If there are only two values so far, C<*> assumes an arithmetic
-progression.  If there is only one value (or if the final values do
-not support the requisite arithmetic), C<*> assumes incrementation
-via C<.succ>.  Hence these come out the same:
+That is, supposing we call the last three numbers C<$a>, C<$b>, and
+C<$c>, and then define:
 
-    1..*
-    1...*
-    1,2,3...*
+    $ab = $b - $a;
+    $bc = $c - $b;
 
-If list on the left is C<Nil>, C<*> will return a single C<Nil>.
+If C<$ab == $bc> and C<$ab> is not zero, then we deduce an arithmetic
+progression determined by the function C<*+$ab>.  If C<$ab> is zero,
+and the three values look like numbers, then the function is C<*+0>.
+If they do not look like numbers, then the function selected is either
+C<*.succ> or C<*.pred> depending on whether C<$b cmp $c> appears to be
+Increasing or Decreasing.  If C<cmp> returns Same then an identity
+function is assumed.
 
-Conjecture: other such patterns may be recognized in the future,
-depending on which unrealistic benchmarks we want to run faster.  C<:)>
+If C<$ab != $bc> and C<none($a,$b,$c) == 0>, then a similar calculation
+is done using division rather than subtraction to determine whether
+a geometric progression is warranted.  Define:
 
-The function may choose to terminate its list by returning ().
+    $ab = $b / $a;
+    $bc = $c / $b;
+    
+If the two quotients are equal (and finite), then a geometric
+function of C<{$_ * $bc}> is deduced.
+
+If there are only two values in the list so far, C<$a> and C<$b>, and the 
difference C<$ab>
+is non-zero, we assume an arithmetic progression of C<*+$ab>.  If C<$ab>
+is zero, then again it depends on whether the two values look like
+numbers whether we use C<*+0> or C<*.succ>/C<*.pred>.
+
+If there is only one value, C<*> always assumes incrementation via
+C<.succ>.  (This may be forced to C<.pred> by examination of a limit,
+as specified below.)  Hence these come out the same:
+
+    1 .. *
+    1 ... *
+    1,2 ... *
+    1,2,3 ... *
+    <1 2 3> ... *   # (but note: first 3 elements are of Str type!)
+
+Likewise these come out the same:
+
+    'a' .. *
+    'a' ... *
+    'a','b' ... *
+    'a','b','c' ... *
+    <a b c> ... *
+
+If the list on the left is C<Nil>, C<*> uses the function {Nil}
+
+When an explicit function is used, it
+may choose to terminate its list by returning ().
 Since this operator is list associative, an inner function may be
 followed by a C<...> and another function to continue the list,
 and so on.  Hence,
@@ -1811,7 +1847,7 @@
 If the right operand is a list and the first element of the list is
 a function or C<*>, the second element of the list imposes a limit
 on the prior sequence.  (The limit is inclusive on an exact match,
-and in general is compared using C<!after> semantics, so an inexact
+and in general is compared using C<!after> or C<!before> semantics, so an 
inexact
 match is *not* included.)  Hence the preceding example may be rewritten
 
     1   ... * + 1, 9,
@@ -1828,7 +1864,7 @@
 the correct arithmetic progression, so the 30 and 300
 terms are necessary to prevent interpretation as geometric.
 
-If the first element of the list is numeric, a C<*> is assumed
+If the first element of the right-hand list is numeric, a C<*> is assumed
 before it, and the first element is again taken as the limit.
 So the preceding example reduces to:
 
@@ -1839,6 +1875,16 @@
 These rules may seem complicated, but they're essentially just replicating
 what a human does naturally when you say "and so on".
 
+The exact function deduced depends on the direction from the final
+value on the left to the limit value on the right.  If the limit is
+greater than the last value according to C<cmp>, then comparisons
+are done with C<!after>.  If the limit is less, then comparisons are
+done with C<!before>, and if the generator function was C<.succ>, it
+is switched to C<.pred>.  Hence we have this difference:
+
+    'z' .. 'a'   # null range
+    'z' ... 'a'  # z y x ... a
+
 Note that the sequence
 
     1.0 ... *+0.2, 2.0
@@ -1881,10 +1927,27 @@
 
 To preserve Perl 5 semantics, you'd need something like:
 
-    'A' ... { my $new = $_.succ; $_ ne $endpoint and $new.chars <= 1 ?? $new 
!! () }
+    'A' ... -> $old { my $new = $old.succ; $old ne $endpoint and $new.chars <= 
1 ?? $new !! () }
 
 But since lists are lazy in Perl 6, we don't try to protect the user this way.
 
+The astute reader will note that
+
+    'A' ... 'Z'
+
+doesn't terminate with a simple C<!after> test either.  The actual function 
used
+is something like:
+
+    'A' ... -> $old { my $new = $old.succ; $old ne 'Z' and $new !after 'Z' ?? 
$new !! () }
+
+Likewise, since Z comes after A:
+
+    'Z' ... 'A'
+
+uses the function:
+
+    'Z' ... -> $old { my $new = $old.pred; $old ne 'A' and $new !before 'A' ?? 
$new !! () }
+
 =back
 
 Many of these operators return a list of C<Capture>s, which depending on

Reply via email to