in reply to Re: ||= oddity
in thread ||= oddity

You may call me stupid, but why can't the scalar result of ||= be assigned to an array?

This works:

$ perl -wle 'my @a = 2; print @a' 2 $ perl -wle 'my @a = scalar 2; print @a' 2 $ perl -wle 'my @a = 2+2; print @a' 4

So we can see that you can assign a scalar to an array, and it does what you mean - it creates an array with one item.

But why can't you do it with the result of @array ||(1, 2, 3)?

Replies are listed 'Best First'.
Re^3: ||= oddity
by almut (Canon) on May 29, 2008 at 13:27 UTC

    ... because it's been designed and implemented to operate the way it does — that's all :)

    I think the crucial difference is that the normal assignment operator (=) does not force scalar context upon its LHS (so the array remains an array, not the number of its elements), while ||= does.  It's not so much an issue of not being able to assign a scalar to an array, but rather the problem of the array no longer being (treated like) an array internally...

Re^3: ||= oddity
by ikegami (Patriarch) on May 29, 2008 at 20:28 UTC

    If it did work, it would produce useless results.
    Given that (LHS ||= RHS) means (LHS = LHS || RHS),
    Then (@a ||= (1,2,3)) means (@a = @a || (1,2,3)) and thus (@a = $#a+1 || 3).
    Why would you ever want that.

    On the other hand, it would be useful to expand the definition of the ||= operator so that (@a ||= EXPR) means (@a = @a ? @a : EXPR).
    Similarly, it could be useful to expand the definition of &&= such that (@a &&= EXPR) means (@a = @a ? EXPR : ()).
    However, none of **=, +=, *=, &=, <<=, -=, /=, |=, >>=, .=, %=, ^=, //= and x= would be useful for arrays.

      You're mostly right, but actually LHS || RHS in list context evaluates RHS in list context. Indeed, if you try

      perl -we '@bar = (); @bar = @bar || (1, 2, 3); warn "(@bar)";'
      you see that the array is filled with the right values: (1, 2, 3); but that's still useless for indeed when the array isn't empty at the beginning,
      perl -we '@bar = (42, 5); @bar = @bar || (1, 2, 3); warn "(@bar)";'
      the or operator returns the length of the array so the array will contain only (2).

      Nice trap.

      However, none of **=, +=, *=, &=, <<=, -=, /=, |=, >>=, .=, %=, ^=, //= and x= would be useful for arrays.

      Actually, x= would be:

      $ perl -we '@bar = (42, 5); (@bar) = (@bar) x 5; warn "(@bar)";' (42 5 42 5 42 5 42 5 42 5) at -e line 1. $ perl -we '@bar = (42, 5); (@bar) x= 5; warn "(@bar)";' Can't modify array dereference in repeat (x) at -e line 1, near "5;" Execution of -e aborted due to compilation errors. $