Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

lvalue reverse and array views

1 view
Skip to first unread message

Juerd

unread,
Nov 19, 2005, 6:49:08 PM11/19/05
to perl6-l...@perl.org
In Perl 5,

for (reverse @foo) { $_ = $_ + 1 }

actually works. But reverse does not return lvalues, which means that:

(reverse @foo) = map $_ + 1, @foo;

does not do the same thing, but actually throws an exception.

I think, but haven't confirmed, that the for-reverse is an
optimization resulting in an undocumented feature. This is something I
hope Perl 6 will avoid, but that raises the following question:

Will Perl 6 support mutable for-reverse?

Some possible answers that I could think of:

(a) Yes, but as a special case
(b) Yes, because reverse returns lvalue aliases
(c) No

But there's another one, that I didn't immediately think of:

(d) Yes, because reverse @foo always behaves like an array (rather than
a function that *returns* a list), just with a different view: the
elements are in the wrong order.

This option d is interesting, and would probably be nice to have,
because it would also allow this (contrived and useless) kind of thing:

push reverse(@foo), $bar;

And while that isn't very interesting, I think something like

my @bar := reverse @foo;

would be very useful. Insert an element between positions 1 and 2, and
the original @foo array gets them between positions -3 and -2.

The same thing would be interesting for zip:

my @xyzzy := @foo Y @bar;

Assuming this results in an even number of elements in @xyzzy, pushing a
single element onto @xyzzy could result in an element added to @foo
every odd, and to @bar every even time.

Would something like that be possible? Wanted? Not too costly?


Juerd
--
http://convolution.nl/maak_juerd_blij.html
http://convolution.nl/make_juerd_happy.html
http://convolution.nl/gajigu_juerd_n.html

Daniel Brockman

unread,
Nov 20, 2005, 12:58:10 AM11/20/05
to perl6-l...@perl.org
Juerd <ju...@convolution.nl> writes:

> I think something like
>
> my @bar := reverse @foo;
>
> would be very useful. Insert an element between positions 1 and 2, and
> the original @foo array gets them between positions -3 and -2.

That would be cool. The concept is reminiscent of using a
change of basis to make your coordinates look nicer in a
vector space or something.

Reversing an array, changing it, and then rereversing it ---
I think that kind of pattern is common.

> The same thing would be interesting for zip:
>
> my @xyzzy := @foo Y @bar;
>
> Assuming this results in an even number of elements in @xyzzy, pushing a
> single element onto @xyzzy could result in an element added to @foo
> every odd, and to @bar every even time.

Well, wouldn't pushing an element onto @xyzzy be more like
pushing the car to @foo and the cdr to @bar, or throwing an
exception if the new element is not a Pair?

(What is Perl's pair terminology, by the way?)

--
Daniel Brockman <dan...@brockman.se>

Juerd

unread,
Nov 20, 2005, 9:45:08 AM11/20/05
to perl6-l...@perl.org
Daniel Brockman skribis 2005-11-20 6:58 (+0100):

> Well, wouldn't pushing an element onto @xyzzy be more like
> pushing the car to @foo and the cdr to @bar, or throwing an
> exception if the new element is not a Pair?

Zipping has nothing to do with pairs, though!

Consider, for example:

@foo Y @bar Y @baz

> (What is Perl's pair terminology, by the way?)

A Pair has a key and a value. To retrieve the key, use the .key method,
to retrieve the value, use the .value method, to retrieve a list of
both, use the .kv method.

Ingo Blechschmidt

unread,
Nov 20, 2005, 10:44:35 AM11/20/05
to perl6-l...@perl.org
Hi,

Juerd wrote:
> Will Perl 6 support mutable for-reverse?

I'd like it! :)

> Some possible answers that I could think of:
>
> (a) Yes, but as a special case
> (b) Yes, because reverse returns lvalue aliases
> (c) No
>
> But there's another one, that I didn't immediately think of:
>
> (d) Yes, because reverse @foo always behaves like an array (rather
> than a function that *returns* a list), just with a different view:
> the elements are in the wrong order.

Where is the difference (for the user) between a subroutine which
returns an appropriate proxy object and an array?

# Perl 5
sub foo {...}
foo[42]; # really foo([42])

# Perl 6
sub foo {...}
foo[42]; # really (foo())[42]
foo{"Pugs"}; # really (foo()){"Pugs"}
foo<Pugs>; # really (foo()){"Pugs"}

> This option d is interesting, and would probably be nice to have,
> because it would also allow this (contrived and useless) kind of
> thing:
>
> push reverse(@foo), $bar;
>
> And while that isn't very interesting, I think something like
>
> my @bar := reverse @foo;
>
> would be very useful.

Yep :)

(Also note that if we make &reverse return an appropriate proxy object
so this example works, for reverse @array {...} will automatically be
optimized.)

> The same thing would be interesting for zip:
>
> my @xyzzy := @foo Y @bar;
>
> Assuming this results in an even number of elements in @xyzzy, pushing
> a single element onto @xyzzy could result in an element added to @foo
> every odd, and to @bar every even time.
>
> Would something like that be possible? Wanted?

I'd like that as well. (Generally, I'd like to see many lvalue subs and
methods in default Perl 6.)

> Not too costly?

I think it'd even optimize many cases:

for @foo ¥ @bar {...}
# Generating a new array containing @foo ¥ @bar is, thanks to
# zip's laziness, unnecessary.


(BTW, IIUC, per r6622 of S06.pod [1] &zip returns an array of arrayrefs
now:

for zip('a'...; 0...; @foo) -> [$a, $i, $x] { ...}

(Or does for no longer automatically take as much elements from the
input array as needed? I.e. does

my @array = <a b c d>;
for @array -> $a, $b { say "$a $b" }

no longer output "a b\nc d\n", but die?))


--Ingo

[1] http://svn.perl.org/perl6/doc/trunk/design/syn/S06.pod

--Ingo

Juerd

unread,
Nov 20, 2005, 11:03:41 AM11/20/05
to perl6-l...@perl.org
Ingo Blechschmidt skribis 2005-11-20 16:44 (+0100):

> Where is the difference (for the user) between a subroutine which
> returns an appropriate proxy object and an array?

An object is a scalar, an array is an array. Perl has unreferenced
arrays --I like to call them "pure" arrays--, and references to arrays.

A sub can, as far as I know, return a pure array, if the sub is an
lvalue sub. The array that is returned can be tied to be a reversed view
of the original array.

The big difference between pure arrays and referenced arrays, for the
user, is that pure arrays flatten in list context, while referenced
arrays do not. Especially with for, this is very relevant.

I don't know if it is possible for an object to flatten in list context,
but I would be surprised if it turned out to be. Scalars should NEVER
flatten in list context. This includes all references and thus objects.

> I think it'd even optimize many cases:
> for @foo ¥ @bar {...}

All for-optimizations are in the for, in Perl 5. It would be nice to
have these in the actual functions and operators in Perl 6. Then
for-reverse is not a special case anymore, and the optimization is
indeed optimizing other cases too.

> (BTW, IIUC, per r6622 of S06.pod [1] &zip returns an array of arrayrefs
> now:
> for zip('a'...; 0...; @foo) -> [$a, $i, $x] { ...}

Hm, that's sufficiently ugly. Is this really needed?

I quite like how

for @foos Y @bars -> $foo, $bar { ... }

looks, and don't quite like

for @foos Y @bars -> [ $foo, $bar ] { ... }

as much.

> (Or does for no longer automatically take as much elements from the
> input array as needed?

I like the arity-sensitivity solution better, I think.

Ingo Blechschmidt

unread,
Nov 20, 2005, 11:25:11 AM11/20/05
to perl6-l...@perl.org
Hi,

Juerd wrote:
> Ingo Blechschmidt skribis 2005-11-20 16:44 (+0100):
>> Where is the difference (for the user) between a subroutine which
>> returns an appropriate proxy object and an array?
>

> The big difference between pure arrays and referenced arrays, for the
> user, is that pure arrays flatten in list context, while referenced
> arrays do not. Especially with for, this is very relevant.

I'd formulate this as "that @-arrays, i.e. variables whose sigil is @,
flatten in list context, while $-arrayrefs do not".

> I don't know if it is possible for an object to flatten in list
> context, but I would be surprised if it turned out to be.

For sure it is! Recall that "my @array = <a b c>" creates an object.

> Scalars should NEVER flatten in list context.

Yep. Again, I'd formulate this as "variables whose sigil is $ should


NEVER flatten in list context".

> This includes all references

Yep.

> and thus objects.

I disagree -- @array and %hash, created by plain old assignment ("my
@array = <a b c>", "my %hash = (...)"), are objects.

>> I think it'd even optimize many cases:
>> for @foo ¥ @bar {...}
>
> All for-optimizations are in the for, in Perl 5. It would be nice to
> have these in the actual functions and operators in Perl 6. Then
> for-reverse is not a special case anymore, and the optimization is
> indeed optimizing other cases too.

Yep. Also note that "for" is not a special magical construct in Perl 6,
it's a simple subroutine (&statement_control:<for>, with the signature
(*@array, Code *&code)). (Of course, it'll usually be optimized.)

Example:

{
my sub statement_control:<for> (*@array, Code *&code) {
map &code, reverse @array;
}

for <a b c> -> $item { say $item }
# "c\nb\na\n"
}

# for restored, as the modified for went out of scope:
for <a b c> -> $item { say $item }
# "a\nb\nc\n"

>> (BTW, IIUC, per r6622 of S06.pod [1] &zip returns an array of
>> arrayrefs now:
>> for zip('a'...; 0...; @foo) -> [$a, $i, $x] { ...}
>
> Hm, that's sufficiently ugly. Is this really needed?
>
> I quite like how
>
> for @foos Y @bars -> $foo, $bar { ... }
>
> looks, and don't quite like
>
> for @foos Y @bars -> [ $foo, $bar ] { ... }
>
> as much.

I agree completely.

>> (Or does for no longer automatically take as much elements from the
>> input array as needed?
>
> I like the arity-sensitivity solution better, I think.

Me too.


--Ingo

Rob Kinyon

unread,
Nov 20, 2005, 11:07:14 PM11/20/05
to Daniel Brockman, perl6-l...@perl.org
On 11/20/05, Daniel Brockman <dan...@brockman.se> wrote:
> Reversing an array, changing it, and then rereversing it ---
> I think that kind of pattern is common.

I would think that reversing a string, modifying it, then reversing it
back is more common. Does modifying the reversal of a string modify
the original?

Rob

0 new messages