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