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

Forcing an rvalue context on a scalar expression

0 views
Skip to first unread message

Brian McCauley

unread,
May 6, 2003, 8:42:14 AM5/6/03
to
What is the simplest way to force an rvalue context on a scalar
expression?

For example, consider:

my @q;
foo($q[-1]);

This generates "Modification of non-creatable array value attempted,
subscript -1" because it's trying to evaluate $q[-1] as an lvalue but
I just wanted foo's $_[0]=undef.

I can easily, but not very elegantly, fix this by saying:

my $last_q = $q[-1];
foo($last_q);

Or even...

foo(my $last_q = $q[-1]);

Or, without a varaiable, but more perversely...

foo(&{sub { $q[-1] }});

Anyone got any less ugly solutions?

--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\

Anno Siegel

unread,
May 6, 2003, 9:32:12 AM5/6/03
to
Brian McCauley <nob...@mail.com> wrote in comp.lang.perl.misc:

> What is the simplest way to force an rvalue context on a scalar
> expression?
>
> For example, consider:
>
> my @q;
> foo($q[-1]);
>
> This generates "Modification of non-creatable array value attempted,
> subscript -1" because it's trying to evaluate $q[-1] as an lvalue but

Isn't that a bug? I mean, you're not assigning anything, are you?

> I just wanted foo's $_[0]=undef.
>
> I can easily, but not very elegantly, fix this by saying:
>
> my $last_q = $q[-1];
> foo($last_q);
>
> Or even...
>
> foo(my $last_q = $q[-1]);
>
> Or, without a varaiable, but more perversely...
>
> foo(&{sub { $q[-1] }});

Along the same line as sub {...}:

foo( do { $q[-1] } );

and, found coincidentally, and not quite understood:

do( scalar $q[ -1]);

I still think it's a bug. Why should scalar vs. list context make
a difference?

Anno

Abigail

unread,
May 6, 2003, 11:54:40 AM5/6/03
to
Brian McCauley (nob...@mail.com) wrote on MMMDXXXV September MCMXCIII in
<URL:news:u98ytk6...@wcl-l.bham.ac.uk>:
:} What is the simplest way to force an rvalue context on a scalar

:} expression?
:}
:} For example, consider:
:}
:} my @q;
:} foo($q[-1]);
:}
:} This generates "Modification of non-creatable array value attempted,
:} subscript -1" because it's trying to evaluate $q[-1] as an lvalue but
:} I just wanted foo's $_[0]=undef.

The problem is your use of -1 as index on an empty array. An empty array
has no elements, so it certainly doesn't have a last element. Due to Perl
using 'call by implicite reference' when calling functions with arguments,
it must know which element you mean, just in case foo assigns to $_ [0].

Consider this:

sub foo {$_ [0] = 1}
my @q;
foo $q [2];
print scalar @q;

This prints 3 because you created $q [2]. But suppose you had called
'foo $q [-1]', how large should @q be afterwards? Which element was
created?

:}
:} I can easily, but not very elegantly, fix this by saying:


:}
:} my $last_q = $q[-1];
:} foo($last_q);
:}
:} Or even...
:}
:} foo(my $last_q = $q[-1]);
:}
:} Or, without a varaiable, but more perversely...
:}
:} foo(&{sub { $q[-1] }});
:}
:} Anyone got any less ugly solutions?


I still don't know what you really want to do. Call foo with just one
argument, that argument being undefined? Just do:

foo (undef)

Or if the argument should be modifyable, do:

foo (my $foo)


Maybe you want @q to be something after foo is called, but I can't
deduce that from your post.


Abigail
--
sub camel (^#87=i@J&&&#]u'^^s]#'#={123{#}7890t[0.9]9@+*`"'***}A&&&}n2o}00}t324i;
h[{e **###{r{+P={**{e^^^#'#i@{r'^=^{l+{#}H***i[0.9]&@a5`"':&^;&^,*&^$43##@@####;
c}^^^&&&k}&&&}#=e*****[]}'r####'`=437*{#};::'1[0.9]2@43`"'*#==[[.{{],,,1278@#@);
print+((($llama=prototype'camel')=~y|+{#}$=^*&[0-9]i@:;`"',.| |d)&&$llama."\n");

Brian McCauley

unread,
May 6, 2003, 12:52:03 PM5/6/03
to
anno...@lublin.zrz.tu-berlin.de (Anno Siegel) writes:

> Brian McCauley <nob...@mail.com> wrote in comp.lang.perl.misc:
> > What is the simplest way to force an rvalue context on a scalar
> > expression?
> >
> > For example, consider:
> >
> > my @q;
> > foo($q[-1]);
> >
> > This generates "Modification of non-creatable array value attempted,
> > subscript -1" because it's trying to evaluate $q[-1] as an lvalue but
>
> Isn't that a bug? I mean, you're not assigning anything, are you?

No, see Abigail's explaination of what's going on.

> > foo(&{sub { $q[-1] }});
>
> Along the same line as sub {...}:
>
> foo( do { $q[-1] } );
>
> and, found coincidentally, and not quite understood:
>
> do( scalar $q[ -1]);

Strange! By rights _neither_ of those should work. Both do{} and
scalar() still return lvalues. If using $q[-1] in an lvalue context
where @q=() is wrong then it should always be wrong.

Hmmm... actually it's probably good that do{} works this way, perhaps
do{} should be documented as behaving this way then we could rely on
it.

Steven Kuo

unread,
May 6, 2003, 3:05:50 PM5/6/03
to
On 6 May 2003, Brian McCauley wrote:

> What is the simplest way to force an rvalue context on a scalar
> expression?
>
> For example, consider:
>
> my @q;
> foo($q[-1]);
>
> This generates "Modification of non-creatable array value attempted,
> subscript -1" because it's trying to evaluate $q[-1] as an lvalue but
> I just wanted foo's $_[0]=undef.
>
> I can easily, but not very elegantly, fix this by saying:
>
> my $last_q = $q[-1];
> foo($last_q);
>
> Or even...
>
> foo(my $last_q = $q[-1]);
>
> Or, without a varaiable, but more perversely...
>
> foo(&{sub { $q[-1] }});
>
> Anyone got any less ugly solutions?
>
>

Do you consider this less ugly?

foo(${\(defined $q[-1]? $q[-1]: undef)});


--
Regards,
Steven

Anno Siegel

unread,
May 6, 2003, 5:21:32 PM5/6/03
to
Brian McCauley <nob...@mail.com> wrote in comp.lang.perl.misc:
> anno...@lublin.zrz.tu-berlin.de (Anno Siegel) writes:
>
> > Brian McCauley <nob...@mail.com> wrote in comp.lang.perl.misc:
> > > What is the simplest way to force an rvalue context on a scalar
> > > expression?
> > >
> > > For example, consider:
> > >
> > > my @q;
> > > foo($q[-1]);
> > >
> > > This generates "Modification of non-creatable array value attempted,
> > > subscript -1" because it's trying to evaluate $q[-1] as an lvalue but
> >
> > Isn't that a bug? I mean, you're not assigning anything, are you?
>
> No, see Abigail's explaination of what's going on.
>
> > > foo(&{sub { $q[-1] }});
> >
> > Along the same line as sub {...}:
> >
> > foo( do { $q[-1] } );
> >
> > and, found coincidentally, and not quite understood:
> >
> > do( scalar $q[ -1]);
>
> Strange! By rights _neither_ of those should work. Both do{} and
> scalar() still return lvalues. If using $q[-1] in an lvalue context
> where @q=() is wrong then it should always be wrong.

But there is no lvalue context for a subroutine argument, otherwise
foo( 'xyz') would be an error. Only if you try to assign to $_[ 0]
in the sub an error happens. $q[ -1] should behave the same way.
After all, it's legal to read an undef from large negative array indices
in other situations.

> Hmmm... actually it's probably good that do{} works this way, perhaps
> do{} should be documented as behaving this way then we could rely on
> it.

I don't think any workaround is needed in the long run. It's a bug in
5.8.0 (I haven't checked bleadperl).

Anno

Anno Siegel

unread,
May 6, 2003, 5:33:47 PM5/6/03
to
Abigail <abi...@abigail.nl> wrote in comp.lang.perl.misc:

> Brian McCauley (nob...@mail.com) wrote on MMMDXXXV September MCMXCIII in
> <URL:news:u98ytk6...@wcl-l.bham.ac.uk>:
> :} What is the simplest way to force an rvalue context on a scalar
> :} expression?
> :}
> :} For example, consider:
> :}
> :} my @q;
> :} foo($q[-1]);
> :}
> :} This generates "Modification of non-creatable array value attempted,
> :} subscript -1" because it's trying to evaluate $q[-1] as an lvalue but
> :} I just wanted foo's $_[0]=undef.
>
> The problem is your use of -1 as index on an empty array. An empty array
> has no elements, so it certainly doesn't have a last element. Due to Perl
> using 'call by implicite reference' when calling functions with arguments,
> it must know which element you mean, just in case foo assigns to $_ [0].
>
> Consider this:
>
> sub foo {$_ [0] = 1}
> my @q;
> foo $q [2];
> print scalar @q;
>
> This prints 3 because you created $q [2]. But suppose you had called
> 'foo $q [-1]', how large should @q be afterwards? Which element was
> created?

All true, but the error shouldn't happen just because foo( $q[ -1]) is
called, only when foo() actually tries to assign to its argument.

Anno

Uri Guttman

unread,
May 6, 2003, 5:56:25 PM5/6/03
to
>>>>> "AS" == Anno Siegel <anno...@lublin.zrz.tu-berlin.de> writes:

AS> Abigail <abi...@abigail.nl> wrote in comp.lang.perl.misc:


>>
>> Consider this:
>>
>> sub foo {$_ [0] = 1}
>> my @q;
>> foo $q [2];
>> print scalar @q;
>>
>> This prints 3 because you created $q [2]. But suppose you had called
>> 'foo $q [-1]', how large should @q be afterwards? Which element was
>> created?

AS> All true, but the error shouldn't happen just because foo( $q[ -1]) is
AS> called, only when foo() actually tries to assign to its argument.

but a sub call creates an alias to that element which doesn't exist. it
can be undef since there is no slot to create alias to.

this generates the same error so it is not a sub related problem. you
can't take a ref or make an alias to an unknown slot in the array. the
-1 index implies you have at least one slot in the array so you can get
its size and index from the end.

perl -e '$r = \$a[-1]'
Modification of non-creatable array value attempted, subscript -1 at -e line 1.

it is the -1 index which is causing the problem and i don't feel it is a
bug. you can't index from the end when you have no elements - there is
no end to use.

uri

--
Uri Guttman ------ u...@stemsystems.com -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org

Abigail

unread,
May 6, 2003, 6:16:24 PM5/6/03
to
Steven Kuo (sk...@mtwhitney.nsc.com) wrote on MMMDXXXV September MCMXCIII
in <URL:news:Pine.GSO.4.21.030506...@mtwhitney.nsc.com>:

<>
<> Do you consider this less ugly?
<>
<> foo(${\(defined $q[-1]? $q[-1]: undef)});


Why not:

foo (@q ? $q [-1] : undef)


Abigail
--
BEGIN {$^H {join "" => ("a" .. "z") [8, 13, 19, 4, 6, 4, 17]} = sub
{["", "Just ", "another ", "Perl ", "Hacker\n"] -> [shift]};
$^H = hex join "" => reverse map {int ($_ / 2)} 0 .. 4}
print 1, 2, 3, 4;

Steven Kuo

unread,
May 6, 2003, 6:50:10 PM5/6/03
to
On 6 May 2003, Abigail wrote:

> Steven Kuo (sk...@mtwhitney.nsc.com) wrote on MMMDXXXV September MCMXCIII
> in <URL:news:Pine.GSO.4.21.030506...@mtwhitney.nsc.com>:
> <>
> <> Do you consider this less ugly?
> <>
> <> foo(${\(defined $q[-1]? $q[-1]: undef)});
>
>
> Why not:
>
> foo (@q ? $q [-1] : undef)
>
>
> Abigail
>


Yours is simpler and more easily read.

I seem to have this bad habit of using or writing ${\(...)} or @{[...]}
in an overly ornate fashion. :(

For example,

I tend to write:

my $aref = \@{[bar()]};

when I really should write:

my $aref = [ bar() ];

sub bar {
return qw(0 2 4);
}

... Must rid myself of this habit.

--
Regards,
Steve

Anno Siegel

unread,
May 6, 2003, 6:51:44 PM5/6/03
to
Uri Guttman <u...@stemsystems.com> wrote in comp.lang.perl.misc:

> >>>>> "AS" == Anno Siegel <anno...@lublin.zrz.tu-berlin.de> writes:
>
> AS> Abigail <abi...@abigail.nl> wrote in comp.lang.perl.misc:
> >>
> >> Consider this:
> >>
> >> sub foo {$_ [0] = 1}
> >> my @q;
> >> foo $q [2];
> >> print scalar @q;
> >>
> >> This prints 3 because you created $q [2]. But suppose you had called
> >> 'foo $q [-1]', how large should @q be afterwards? Which element was
> >> created?
>
> AS> All true, but the error shouldn't happen just because foo( $q[ -1]) is
> AS> called, only when foo() actually tries to assign to its argument.
>
> but a sub call creates an alias to that element which doesn't exist. it
> can be undef since there is no slot to create alias to.


...but $q[ 12] doesn't exist either, but is legal in places where $q[ -1]
isn't. The difference would be that (with an empty array) $q[ -1] can
never be allocated.

I don't understand the second sentence.

> this generates the same error so it is not a sub related problem. you
> can't take a ref or make an alias to an unknown slot in the array. the
> -1 index implies you have at least one slot in the array so you can get
> its size and index from the end.
>
> perl -e '$r = \$a[-1]'
> Modification of non-creatable array value attempted, subscript -1 at -e line 1.

Hmm... referencing and aliasing seems to be the key. "1 for $q[ -1]"
also triggers it. Still, the behavior is unexpected, considering that
read-access is usually possible with any array and any index, even
large negatives. Also, how can a prepended "scalar", or a "do{}"
wrapped around heal it? Something is flaky here and needs attention.

> it is the -1 index which is causing the problem and i don't feel it is a
> bug. you can't index from the end when you have no elements - there is
> no end to use.

Ah, c'mon, 0 is a respectable end too. Emptiness has nothing to do
with it, the same happens with a non-empty array for large negative
indices, once they point past (err, before) the beginning of the array.

I still think there's a bug involved, but the solution may be less
straight-forward than I was hoping for.

Anno

Uri Guttman

unread,
May 6, 2003, 10:55:32 PM5/6/03
to
>>>>> "AS" == Anno Siegel <anno...@lublin.zrz.tu-berlin.de> writes:

AS> Uri Guttman <u...@stemsystems.com> wrote in comp.lang.perl.misc:


>> >>>>> "AS" == Anno Siegel <anno...@lublin.zrz.tu-berlin.de> writes:
>>
AS> Abigail <abi...@abigail.nl> wrote in comp.lang.perl.misc:
>> >>
>> >> Consider this:
>> >>
>> >> sub foo {$_ [0] = 1}
>> >> my @q;
>> >> foo $q [2];
>> >> print scalar @q;
>> >>
>> >> This prints 3 because you created $q [2]. But suppose you had called
>> >> 'foo $q [-1]', how large should @q be afterwards? Which element was
>> >> created?
>>
AS> All true, but the error shouldn't happen just because foo( $q[ -1]) is
AS> called, only when foo() actually tries to assign to its argument.
>>
>> but a sub call creates an alias to that element which doesn't exist. it
>> can be undef since there is no slot to create alias to.


AS> ...but $q[ 12] doesn't exist either, but is legal in places where $q[ -1]
AS> isn't. The difference would be that (with an empty array) $q[ -1] can
AS> never be allocated.

AS> I don't understand the second sentence.

i said the same thing but in a different way. $q[12] can be allocated
since it can count from the 0 slot. $q[-1] can't be located nor
allocated since it must count from the end and the array is empty. -1
would then mean the 'real' -1 slot which can't be accessed.

simple math here. the negative numbers are based on the array size. if
the array has 1 element, a -1 index refers to the 0 slot (1 - 1). so if
the array is empty it refers to the (0 - 1) -1 slot which cannot exist.


AS> Hmm... referencing and aliasing seems to be the key. "1 for $q[ -1]"
AS> also triggers it. Still, the behavior is unexpected, considering that
AS> read-access is usually possible with any array and any index, even
AS> large negatives. Also, how can a prepended "scalar", or a "do{}"
AS> wrapped around heal it? Something is flaky here and needs attention.

dunno how they 'fix' it. i still don't consider it a bug as my math
above shows. an empty array doesn't have a -1 slot.

AS> Ah, c'mon, 0 is a respectable end too. Emptiness has nothing to do
AS> with it, the same happens with a non-empty array for large negative
AS> indices, once they point past (err, before) the beginning of the array.

it is the size and not the end index that is used in the negative index
calculation. look at the above.


AS> I still think there's a bug involved, but the solution may be less
AS> straight-forward than I was hoping for.

i think the scalar and do{} fixes may be bugs. :)

i haven't looked into their behavior and i may later.

Anno Siegel

unread,
May 7, 2003, 5:46:20 AM5/7/03
to

Sure. All I'm saying is the effect isn't bound to empty arrays but
happens whenever a negative index exceeds the array bound.

> AS> Hmm... referencing and aliasing seems to be the key. "1 for $q[ -1]"
> AS> also triggers it. Still, the behavior is unexpected, considering that
> AS> read-access is usually possible with any array and any index, even
> AS> large negatives. Also, how can a prepended "scalar", or a "do{}"
> AS> wrapped around heal it? Something is flaky here and needs attention.
>
> dunno how they 'fix' it. i still don't consider it a bug as my math
> above shows. an empty array doesn't have a -1 slot.
>
> AS> Ah, c'mon, 0 is a respectable end too. Emptiness has nothing to do
> AS> with it, the same happens with a non-empty array for large negative
> AS> indices, once they point past (err, before) the beginning of the array.
>
> it is the size and not the end index that is used in the negative index
> calculation. look at the above.
>
>
> AS> I still think there's a bug involved, but the solution may be less
> AS> straight-forward than I was hoping for.
>
> i think the scalar and do{} fixes may be bugs. :)
>
> i haven't looked into their behavior and i may later.

There is clearly a bug involved and it is independent from the "$q{ -1}"
behavior.

my $x;
scalar( $x) = 123;

Can't modify scalar in scalar assignment at ...

$_ = 123 for scalar( $x);
print "$x\n";

123

Similar behavior with "sub assign { $_[ 0] = 123 }; assign( scalar( $x))"
and with "do {}" instead of "scalar()". That can't be all correct.

But I think this is only indirectly related to the behavior of "$q[ -1]"
(with empty @q).

As to that, I still believe if it can be fixed with reasonable expense
it should be. Since read access to $q[ -1] is legal elsewhere, it
comes as a surprise that it can't be used in "aliasing context" (like
a sub parameter, or an element in a "foreach" list).

I may be naive, but I'd try to supplant an alias to a read-only
location with undefined content for the un-creatable alias. That
way an error would only occur if you try to assign to the location,
the read behavior would be as it should be.

Anno

Uri Guttman

unread,
May 7, 2003, 10:11:15 AM5/7/03
to
>>>>> "AS" == Anno Siegel <anno...@lublin.zrz.tu-berlin.de> writes:

AS> There is clearly a bug involved and it is independent from the "$q{ -1}"
AS> behavior.

AS> my $x;
AS> scalar( $x) = 123;

AS> Can't modify scalar in scalar assignment at ...

AS> $_ = 123 for scalar( $x);
AS> print "$x\n";

AS> 123

lvalue and aliasing are not the same thing internally. it could be
classified as a bug. report it to p5p and let them fight over it.

AS> I may be naive, but I'd try to supplant an alias to a read-only
AS> location with undefined content for the un-creatable alias. That
AS> way an error would only occur if you try to assign to the location,
AS> the read behavior would be as it should be.

i disagree. it think it should stay a runtime error. maybe the scalar/do
stuff that works should also fail. again, let p5p hash it out. these are
not things i will ever run into in my code so i don't have much concern
about them. they are all poor user code and odd corner cases.

Brian McCauley

unread,
May 7, 2003, 12:36:47 PM5/7/03
to
Abigail <abi...@abigail.nl> writes:

> Steven Kuo (sk...@mtwhitney.nsc.com) wrote on MMMDXXXV September MCMXCIII
> in <URL:news:Pine.GSO.4.21.030506...@mtwhitney.nsc.com>:
> <>
> <> Do you consider this less ugly?
> <>
> <> foo(${\(defined $q[-1]? $q[-1]: undef)});
>
>
> Why not:
>
> foo (@q ? $q [-1] : undef)

That's a very simple and elegant solution in the specific case of the
example of $q[-1] causing "Modification of non-creatable array value
attempted". You are focusing too closely on the simplified example
used to illustrate the question and not the actual question. In the
original situation I happend to encounter this was really more like
func()->[-1] where func() is quite expensive.

The question (see subject line) was "forcing an rvalue context". The
expression $q[-1] was just an example of the type of expression on
which one may want to do this.

Once again I think you are falling into the trap of trying to globally
optomise illustative examples. Programming examples often optomise
away completely because they do not do anything.

Steven Kuo

unread,
May 7, 2003, 1:54:25 PM5/7/03
to
On 7 May 2003, Brian McCauley wrote:

> Abigail <abi...@abigail.nl> writes:
>
> > Steven Kuo (sk...@mtwhitney.nsc.com) wrote

> > <> ...

> > <>
> > <> foo(${\(defined $q[-1]? $q[-1]: undef)});
> >
> >
> > Why not:
> >
> > foo (@q ? $q [-1] : undef)
>
> That's a very simple and elegant solution in the specific case of the
> example of $q[-1] causing "Modification of non-creatable array value
> attempted". You are focusing too closely on the simplified example
> used to illustrate the question and not the actual question. In the
> original situation I happend to encounter this was really more like
> func()->[-1] where func() is quite expensive.
>
> The question (see subject line) was "forcing an rvalue context". The
> expression $q[-1] was just an example of the type of expression on
> which one may want to do this.
>
> Once again I think you are falling into the trap of trying to globally
> optomise illustative examples. Programming examples often optomise
> away completely because they do not do anything.
>

But it seems that even if func()->[-1] were expensive, you could do
this:


#! /usr/local/bin/perl
use strict;
use warnings;
use Data::Dumper;

bar(@{[func()->[-1]]});
bar(@{[func(1)->[-1]]});

# -- Modification error:
# bar(func()->[-1]);

# -- Seems okay:
# bar(do {func()->[-1]});


sub func {
my @array = $_[0]? (3, 2, '') : ();
return \@array;
}

sub bar {
print Dumper $_[0];
}


Or is there some performance penalty that I've not recognized?


--
Regards,
Steven

Brian McCauley

unread,
May 7, 2003, 3:46:37 PM5/7/03
to
Steven Kuo <sk...@mtwhitney.nsc.com> writes:

> On 7 May 2003, Brian McCauley wrote:
>
> > Abigail <abi...@abigail.nl> writes:
> >
> > > foo (@q ? $q [-1] : undef)
> >
> > That's a very simple and elegant solution in the specific case of the
> > example of $q[-1] causing "Modification of non-creatable array value
> > attempted". You are focusing too closely on the simplified example
> > used to illustrate the question and not the actual question. In the
> > original situation I happend to encounter this was really more like
> > func()->[-1] where func() is quite expensive.

> But it seems that even if func()->[-1] were expensive, you could do
> this:
>
> bar(@{[func()->[-1]]});

Ah, yes. The famous @{[]} construct! I was forgetting that little
marvel (despite the fact that I use it often in other contexts).

Thankyou.

0 new messages