Logical or assignment and array

A

Adrien BARREAU

Hello all.


Here is a piece of code that troubles me:

=====
$ perl -e 'my @a; @a = @a || 1..3;'
$ perl -e 'my @a; @a ||= 1..3;'
Can't modify private array in logical or assignment (||=) at -e line 1,
near "3;"
Execution of -e aborted due to compilation errors.
=====

It thought the "a operator= b" notation really was "a = a operator b",
but it seems it is wrong.

Does anyone have some information about this?


Adrien.
 
G

George Mpouras

Στις 14/1/2014 13:01, ο/η Adrien BARREAU έγÏαψε:
Hello all.


Here is a piece of code that troubles me:

=====
$ perl -e 'my @a; @a = @a || 1..3;'
$ perl -e 'my @a; @a ||= 1..3;'
Can't modify private array in logical or assignment (||=) at -e line 1,
near "3;"
Execution of -e aborted due to compilation errors.
=====

It thought the "a operator= b" notation really was "a = a operator b",
but it seems it is wrong.

Does anyone have some information about this?


Adrien.




it have to do with left/right precedence the following works


my @a;
@a = qw/a b/;
@a or @a=1..3;

$,="\n"; print @a;
 
R

Rainer Weikusat

Ben Morrow said:
In the statement

@a = @a || 1..3;

the first '@a' is in list context and the second is in scalar context.

I doubt that this expression means what the OP thinks it means, cf

perl -e '@b = (4,5,6); @a = @b || 1 .. 3; print @a;'

This prints 3 because evaluating @b in scalar context returns the size
of the array.
This means they can't be combined into a single argument to the ||=
operator.

I think this is because if the LHS of the assignment were a list it
would be impossible to evaluate that list in both contexts without
evaluating it twice (which ||= promises not to do).

The @a in @a ||= parses as OP_RV2AV and the Perl_mod routine in op.c
(5.10.1) which is used to

Propagate lvalue ("modifiable") context to an op and its
children. 'type' represents the context type, roughly based on
the type of op that would do the modifying, although local() is
represented by OP_NULL. It's responsible for detecting things
that can't be modified,

type is OP_ASSIGN which is classifed as 'scalar mod type' by the
function of the same name and Perl_mod rejects the assignment because of
that.

Logically, one could regard this as '@a evaluated in scalar context', as
required by the || part of ||=, yields the size of a and since this is
an integer constant, it can't be assigned to.
 
R

Rainer Weikusat

Ben Morrow said:
In the statement

@a = @a || 1..3;

the first '@a' is in list context and the second is in scalar context.

I doubt that this expression means what the OP thinks it means, cf

perl -e '@b = (4,5,6); @a = @b || 1 .. 3; print @a;'

This prints 3 because evaluating @b in scalar context returns the size
of the array.
This means they can't be combined into a single argument to the ||=
operator.

I think this is because if the LHS of the assignment were a list it
would be impossible to evaluate that list in both contexts without
evaluating it twice (which ||= promises not to do).

The @a in @a ||= parses as OP_RV2AV and the Perl_mod routine in op.c
(5.10.1) which is used to

Propagate lvalue ("modifiable") context to an op and its
children. 'type' represents the context type, roughly based on
the type of op that would do the modifying, although local() is
represented by OP_NULL. It's responsible for detecting things
that can't be modified,

type is OP_ORASSIGN which is classifed as 'scalar mod type' by the
function of the same name and Perl_mod rejects the assignment because of
that.

Logically, one could regard this as '@a evaluated in scalar context', as
required by the || part of ||=, yields the size of a and since this is
an integer constant, it can't be assigned to.
 
R

Rainer Weikusat

[...]
The @a in @a ||= parses as OP_RV2AV and the Perl_mod routine in op.c
(5.10.1) which is used to

Propagate lvalue ("modifiable") context to an op and its
children. 'type' represents the context type, roughly based on
the type of op that would do the modifying, although local() is
represented by OP_NULL. It's responsible for detecting things
that can't be modified,

type is OP_ORASSIGN which is classifed as 'scalar mod type' by the
function of the same name and Perl_mod rejects the assignment because of
that.

Remotely Enlish variant: "The Perl_mod routine which is used to [...]
rejects the assignment because the type is [...] which is [...]"
 
T

Tim McDaniel

In the statement

@a = @a || 1..3;

the first '@a' is in list context and the second is in scalar
context.

The first time, I misread what you actually wrote. The second
occurrence of @a in the whole line (the first operand of ||) is
evaluated in a scalar context. 1..3 (the second operand of ||) as
stated in "man perlop" should be evaluated in a list context:

C-style Logical Or

Binary "||" performs a short-circuit logical OR operation.
That is, if the left operand is true, the right operand is
not even evaluated. Scalar or list context propagates down
to the right operand if it is evaluated.
 
T

Tim McDaniel

I doubt that this expression means what the OP thinks it means, cf

perl -e '@b = (4,5,6); @a = @b || 1 .. 3; print @a;'

This prints 3 because evaluating @b in scalar context returns the size
of the array.

that is, trying to do this

@a = @a || 1..3;

to mean "if @a has no elements, supply defaults", only works if @a has
no elements.

I've certainly used the scalar version,

$arg ||= 'default';

A pity that it doesn't work for arrays. Is there a nice concise way
to do it for arrays?

@a = 1..3 if !@a;

@a = @a ? @a : 1..3;

Neither of those is quite as nice.
 
R

Rainer Weikusat

[...]
perl -e '@b = (4,5,6); @a = @b || 1 .. 3; print @a;'

This prints 3 because evaluating @b in scalar context returns the size
of the array.

that is, trying to do this

@a = @a || 1..3;

to mean "if @a has no elements, supply defaults", only works if @a has
no elements.

I've certainly used the scalar version,

$arg ||= 'default';

A pity that it doesn't work for arrays. Is there a nice concise way
to do it for arrays?

@a = 1..3 if !@a;

@a = @a ? @a : 1..3;

@a or @a = 1 .. 3

or

!@a and @a = 1 .. 3

would be two other options.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top