develooper Front page | perl.perl6.language | Postings from April 2003

RE: Fun with multi-dimension arrays

Thread Previous | Thread Next
From:
Austin Hastings
Date:
April 26, 2003 20:45
Subject:
RE: Fun with multi-dimension arrays
Message ID:
ICELKKFHGNOHCNCCCBKFIECFCEAA.Austin_Hastings@Yahoo.com


> -----Original Message-----
> From: Luke Palmer [mailto:fibonaci@babylonia.flatirons.org]
> Sent: Saturday, April 26, 2003 8:31 PM
> To: dave@whipp.name
> Cc: perl6-language@perl.org
> Subject: Re: Fun with multi-dimension arrays
>
>
> > I was having fun with a game of life over on perl monks
> (node_id=253366)
> > -- writing "real" Perl6 code -- and I realised there were a few things
> > that I wanted arrays/loops to do, that I'm not entirely sure
> that they can.
> >
> > Lets start with something simple:
> >
> >    for @x.kv -> $k,$v { print "$k = $v\n" }
> >
> > That works fine. But can I do
> >
> >    for @x -> $v { print "$v.key = $v\n" }
> >
> > I.e. does a loop variable maintain a connection to its iterator.
>
> No.  First, that would need to be:
>
>     print "$v.key() = $v\n"
>
> And second, that would be calling the key() method on whatever element
> $v was referring to.  You can do the .kv way above, or:
>
>     for zip(@x, 0...) -> $k,$v {...}

Backwards, ain'a? $v, $k

(I'm in Wisconsin right now...)

>
> > C<Fo> being a builtin, the compiler could easily do that behind the
> > scenes.  For namespace reasons, we might require an explicit trait:
> >
> >    for @x -> $v is keyed { print "$v.key = $v\n" }
> >
> > Presumably a keyed value could also have .prev and .next methods.
> > Perhaps C<keyed> is spelt C<iterator>.
>
> I'd rather not.  It's clear enough one of the other two ways.

Not quite - the .next and .prev thing has some real value, IMO. It's part of
a bundle.

> I don't like delegation on the language level.  It can cause some
> really counterintuitive results (consider an array of pairs).

Yeah - that's why it should be C<is keyed> -- to tell the user that you're
overlaying an implicitly typed iteration-variable-class atop the data nodes.

    for @AofPairs -> $x { print $x.key }
vs
    for @AofPairs -> $x is keyed { print $x.key }

> > Thats the 1-d case. Now what about 2-d arrays:
> >
> >    for *@AofA -> $cell is keyed
> >    {
> >       my ($x, $y) = $cell.key;
> >       print "cell value at ($x,$y) is $cell\n";
> >    }
> >
> > The issue here is whether the lasily flattened array remembers its
> > original index, rather than its flattenned one.
>
> Er, what?
>
> How about:
>
>     for @AofA.kv -> $x, @A {
>         for @A.kv -> $y, $cell {
>             print "cell value at ($x,$y) is $cell\n";
>         }
>     }
>
Works, but doesn't reduce the workload.

> > If we've got this far, what about 3-d arrays. Is It possible to iterate
> > a 3-d grid without using nested loops?
>
> Don't think so.

> Not as if it would be hard to write a multidim() function that could
> behave like so:
>
>     for multidim(@a1, @a2, @a3) -> $x,$y,$x { ... }
>
> Especially with coroutines.

Ehh? You want

sub multidim(*@dims) {
  my @iter;
  my @ranges;

  for @dims {
    my $min = 0;
    my $max = 0;

    when Iter { $min = $_.first; $max = $_.last; }
    when Pair { $min = $_.key;   $max = $_.value; }
    default   { $max = $_; }

    @iter.unshift $min;
    @ranges.unshift $min => $max;
  }

  loop {
    resume *@iter;

    my $ci = 0;

    while @iter[$ci]++ == @ranges[$ci][1] {
      @iter[$ci] = @ranges[$ci][0];
      if ++$ci == @ranges {
        fail;
      }
    }
  }
}

> > The next thing that I wanted to do was to get all the sum of the
> > neighboring points around a cell (remember, this was Game Of Life).
> >
> > Going back to 2-d a moment:
> >
> > First the offsets:
> >
> >    my $offsets_2d = [ -1|0|1, -1|0|1 ] & none([0,0]);
> >
> > Will this work. Will the junction reach outward to make a junction of
> > array-refs?
>
> Hmmm.  I don't know.  I think it would, because we don't want
> junctions popping up where people don't expect them, because their
> logic is so different.  So probably, unless it was declared as an
> array of Junction.

> > For the multi-d (dimension $N) case, would this work?
> >
> >    my $offsets_1d = -1|0|1;
> >
> >    my $offsets = [ ($offsets_1d) x $N ] & none( [ (0) x $N ] );
>
> No, but the idea is right.
>
>     my $offsets_1d = -1|0|1;
>     my $offsets = [ ($offsets_1d) xx $N ] & none( [ (0) xx $N ] );
>
> I don't know whether the parens need to be there on the left of xx,
> but I know it won't hurt if they are.

Is this real? I understand the :: -> xx logic, but where did it come from?

> > OK, having got this far, lets apply out offsets to get coords:
> >
> >    my @neighbors = ( $offsets_2d >>+<< [$x,$y] ).states;
> >
> > I think Ive got this right: both sides of the hyper-plus will
> > dereference their arrays, and elements will be summed. Because the lhs
> > is a junction, the result of the hyper operator will be a junction of
> > corrdinates. I then .states that junction to get the neighborhood: an
> > array of points
>
> Wow.  Well done.
>
> > OK, so thats the junctions. What about access? Given @cell[$x][$y][$z],
> > how do I pass around an index to a cell?
> >
> >    $point = [10, 3, 9];
> >    print @cell[$point]; # is this an array slice, or a single point?
> >
> > Having to write
> >
> >    @cell[$point[0]][$point[1]][$point[2]];
> >
> > could get stale somewhat quick.
>
> True.  I think C<print @cell[$point]> would actually give you the 4th
> element of @cell, though.

Why? Of all the answers possible, 4 wasn't on my list.

(I.e., 9th or 2nd)

> Maybe we need a Key data type that will let you do that:
>
>     my Key $point = [10, 3, 9];
>
> Or some such thing.

Again, why? The only risk is that [] should be () -- create a listref, and
hand it to @array.INDEX() and stand back.

>
> > So lets assume it works.
>
> Spoken like a true computer scientist :)

We imagine a spherical cow of uniform density...

> > Hopefully I can now sum my neighborhood by doing:
> >
> >    my $sum = @neighbors
> >                 ==> map { @cells[$^coordinate }
> >                 ==> sum;
>
> Provided C<sum> is a listop synonym for C<reduce { $^a + $^b }>.

Agree. It's pretty obvious, but also pretty easy to write..

> > Putting this all together, my code the the game-of-life update loop
> > could be:
> >
> > class Life
> > {
> >    has @.grid is array dim(20) of array dim(20) of bit is default(0);
>
> That C<is default(0)> needn't be there, I presume.

Since C<bit> has no "undef", it's a reasonable thing to say, but since the
closest thing to undef is 0, you're probably right -- not needed.

> >    method update
> >    {
> >       my @new_grid is like @.grid;
>
> Huh?  That's a syntax error.  Are you trying to copy it, or specify
> that the type is the same as @.grid's type?  I don't think we have a
> way of doing the latter, but I would assume:
>
>         my @new_grid is typeof(@.grid);
>
> Or something like it would work.

This is another possible use for C<as>, as well.

    my @new_grid is as @.grid;

But now we're just giving english lessons. typeof works just as well,
although in this case I think that there's some question about, for example,
the return value of typeof -- should it be "array of array of bit" or
"array(20, 20) of bit". IOW, does the dimensionality get included? If so,
would it BE included if it weren't specified on the vardecl line? Should
there be a way to copy that info, too?

Hence, C<as> could be defined as an operator which MAKES a subtype out of
environmental context.

Beware.

> >       for *@new_grid -> $cell is rw is keyed
> >       {
> >         $cell = .next_state($cell.key)
>
> This calls .next_state on the current cell.   You need to say

Calls .next_state on current LIFE, not key -- $self is a game.

>           $cell = $self.next_state($cell.key)
>
> It's a shame, too.
>
> >       }
> >       @.grid = @new_grid;
> >    }
>
> Hmm, something tells me this could be done a little more elegantly
> with hypotheticals.

Hypotheticals would be visible in the current namespace - you don't want it
to be visible until you're totally done.

It's a shame, too. I was looking for something like that.

=Austin


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