develooper Front page | perl.perl6.language | Postings from June 2005

Re: reduce metaoperator on an empty list

Thread Previous | Thread Next
From:
=?ISO-8859-1?Q?=22TSa_=28Thomas_Sandla=DF=29=22?=
Date:
June 6, 2005 18:25
Subject:
Re: reduce metaoperator on an empty list
Message ID:
42A4F774.9050907@orthogon.com
HaloO Roger,

I'm answering here to your other mail as well. In my example
I was intensionally changing from last to first and positive
and negative numbers! This is a sublety of distance preserving,
direction aware counting in multiples of arbitrary
unity---or some such ;)

you wrote:
> This is why I would rather the o -> [o] circumfixion left [o] an infix, 
> not prefix operator.  I would rather be explicit about my identity:
> 
>     $product = 1 [*] @array;
> 
>     $factorial = 1 [*] 1..$n;
> 
>     $text = "" [~] @lines;
> 
>     $balance = $balance [-] @debits;
> or
>     $balance [-]= @debits;
> 
> which last suggests how you don't always want to start at the identity, 
> and how [-] makes sense in this context.

Ahh, yes! That also introduces directionality were you reduce from the
front

    $product = 1 [*] @array;

or the back

    $product = @array [*] 1;

The corresponding unary forms are---syntax aside for the moment---
prefix

    $product = [*] @array; # @array[0] [*] @array[0^..^$.end];

and postfix

    $product = @array [*]; #  @array[0..^$.end-1].reverse [*] @array[-1];

Most interesting is that

    $product = @array [*=]; # collects result in @array[-1] and assigns ref

and

    $product = [*=] @array; # collects result in @array[0] and assigns ref




Now I'm following up from my clock example in the mod/div subthread.
I try to illustrate the advantage of the euclidean definition of modulo
division provided as the built-in op %. Completed with the respective
numerics for / according to the division rule.

    #  negative radix, negative digits
    #  [-12] [-11] [-10]  [-9] [-8] [-7] [-6] [-5] [-4] [-3] [-2] [-1]
@d = <  12    01    02    03   04   05   06   07   08   09   10   11 >;
    #  [  0] [  1] [  2] [  3] [ 4] [ 5] [ 6] [ 7] [ 8] [ 9] [10] [11]
    #  negative radix, positive digits

This looks like an obvious application of two's complement which
unfortunately doesn't explain why $x % $y should give the same
result as $x % -$y.

Let's look at the weekdays then. Everybody knows that there are seven
days in a week. Handling the days as ints in 0..6 or 1..7 and doing
naive calculations with them results in typical "off by one"
errors---which are unnecessary if e.g. array and enums are doing
proper modulo arithmetic. Then the forward counting weekdays are
0..^7 and the reverse weekdays are -7..^0. A little overwide picture
demonstrating this is appended.

The idea is to have the real content of an array beeing indexed modulo
it's length. Zero length is of course the empty array. Positive length
is the normal forward array. An array with negative length is an array
iterated from the back. An array's index set is thus giving positions
*between* the content cells. An exhausted forward iterator is after the
last entry, an exhausted backwards iterator is before the first. The
actual content is the remainder which points *into* the array. A slice
is just a pair of positions in such an array.

With the above POV, strings become arrays of character describing
sequences of Unicode numbers. ASCII is e.g. Unicode % 127 :)
With left to right beeing positive direction a big endian digit
string has got negative length!

The real fun starts when multi-dimensional arrays are indexed/iterated.
The array
   # 0 |
@a = ( 0+0/3,  0+1/3,  0+2/3;                   #   3
        1+0/5,  1+1/5,  1+2/5,  1+3/5, 1+4/5;    #  +5
       -1+0/3, -1+1/3, -1+2/3                 )  #  +3 == 11 entries
    #   2+0/3,  2+1/3,  2+2/3                  | 3
can be indexed e.g. @a[1/4] to give the 0 from the first list. That is,
the integer part of 1/4 gives the index 0 in the outer dimension, while
the remainder 0.25 is mapped to the equally subdivided length of @a[0]

+@a[0][] == 1/(3**-1) == 3 # index set is (0, 1/3, 2/3) »/« 1/3 == (0,1,2)

to form the index @a[0][0]. The borderline case is of course
@a[1/3] == @a[0][1]. Well, and +@a[0] == 1 because it's an array ref.
"Overflowing" to the right like @a[4/3] gives @a[1][1] because the second
subarray is indexed with (0, 0.2, 0.4, 0.6, 0.8) and 0.2 <= 1/3 < 0.4 is
in the second cell. Thus @a[9/8] == @a[1][0]. Finally note that

   @a[2/-3] == @a[-1][-2] == -1+1/3   #  two's complement!
                                      #    2 == 3 * 0 + 2  division rule

is *here* quite the same as the negated/reversed content of

   @a[-2/3] == @a.reversed[-1][1] == 0+1/3  # -2 == 3 * (-1) + 1

while the interpretation is different in general!

The first example goes with a positive, fractional index 2/3
from the back *backwards* into the *last* sub-array. That is
counting 3/3 -> 2/3 -> 1/3 from the end of @a[-1].
The second example goes with a positive, fractional index 1/3
from the front *forwards* into the *last* sub-array. That is
counting 0/3 +> 1/3 +> 2/3 where *> is the endpoint of the
iterator.

The complementary pair of index operations is

   @a[ 2/ 3] == @a[0][2] == 0+2/3           #  2 ==   3 *  0 + 2

   @a[-2/-3] == @a.reverse[-1][-1] == 0+2/3  # -2 == (-3) * 1 + 1

With the first case as the usual indexing. The first index
of the second line might look weird but is straight forward
err backwards. That is the double negation case maps to
indexing *backwards* from the reversed outer dimension.
To this reversed array the second negative index goes from
the other end---which is the forward end of @a[0]---into the
array. Basically we use a reverse iterator on an array with
negative length.

In the above treatment the middle array @a[1] was never touched.
Thus I ask myself, how all this endianess maps to the reduce
operator within array slices:

   # ( 0+0/3,  0+1/3,  0+2/3 [;] -1+0/3, -1+1/3, -1+2/3 )

      @a        .[ 0..2  [;] -3..-1].reverse
   == @a.reverse.[-1..-3 [;]  0.. 2]

   == @a        .[  0,  1,  2 [;] -3, -2, -1 ].reverse
   == @a.reverse.[ -3, -2, -1 [;]  0,  1,  2 ]

   == ( -1+2/3, -1+1/3, -1+0/3, 0+2/3, 0+1/3, 0+0/3 )

Call that the DeMorgan of Array Slicing :)
-- 
TSa (Thomas Sandlaß)

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About