lukestyle has asked for the wisdom of the Perl Monks concerning the following question:

Ok so maybe not exactly the correct title, but i'm flummoxed why the first two work as expected, but the third results in an empty array:

1) sub ding { @foo = @{$_[0]}; }

2) sub ding { @bar = @{$_[0] || ()}; }

3) sub ding { @jazz = @{$_[0]} || (); }

Thanks very much,

Luke

update:

I was just interested in comparing why it is that i can copy an array and initialise arraycopy as empty in case array is undefined:
4) @arraycopy = @array || ();

But that i'm not able to follow the same pattern when dereferencing the arrayref in 3)

Would anyone ever do 2), or would they be more verbose?
2b) @bar = defined @{$_[0]} ? @{$_[0]} : ();

update 2:

Well this is embarrasing, Re @choroba: "The || operator forces scalar context on the left operand". I was having one of those crazy moments where I was convinced 4) was what I always did(!) And Then trying to figure why applying the same principal to an array ref in 3) didn't work. I guess I was thinking of (re)initialising an empty array as in simply @array = ();

But forgetting my original question, Re @Eliya: "my @foo = ref $_[0] eq "ARRAY" ? @{$_[0]} : ();" this is better than 2b) and I've learned more to boot. I promise too next time I'll try to explain the boundaries of my question better.

Replies are listed 'Best First'.
Re: Dereference Empty(!) Array
by choroba (Cardinal) on Feb 20, 2012 at 17:54 UTC
    In the third case, you are assigning
    @jazz = ( @{ $_[0] } || () );
    The || operator forces scalar context on the left operand, so it returns the number of elements in the referenced array. If the array is empty, the number is 0, so || works and returns undef, i.e. empty array.
Re: Dereference Empty(!) Array
by ricDeez (Scribe) on Feb 20, 2012 at 21:26 UTC

    As mentioned by others already, your ding sub isn't doing anything terribly useful other than returning as an array the length of the first array passed in by reference. What do you purport to use ding for?

    use warnings; use strict; use 5.012; use Smart::Comments '###'; my @foo; sub ding { @{$_[0]} || (); } my @a = qw(apple banana pear grapes); my @b = qw(lettuce onions); my @c = qw(popcorn ice-cream); @foo = ding(\@a, \@b, \@c); ### @foo #--- Result: #### @foo: [ #### 4 #### ]

    Also, rather than assigning to @foo inside ding and having to rely on the closure (i.e. @foo being defined prior to the sub being defined), why not just return from the sub and assign outside of the sub?

Re: Dereference Empty(!) Array
by JavaFan (Canon) on Feb 20, 2012 at 18:19 UTC
    Since you're not telling us how you're calling ding, I'm not sure what to tell you. If I call ding without arguments, all of @foo, @bar and @jazz end up as empty arrays.

    To make your question complete, can you tell us

    1. How you call ding
    2. What @foo and @bar end up to be, and what you expect @jazz to be?
Re: Dereference Empty(!) Array
by Eliya (Vicar) on Feb 20, 2012 at 19:09 UTC

    Not really sure what you're trying to achieve, i.e. in what way the first two variants "work as expected".

    If the idea is simply to be able to call the routine with a reference to an array which is empty, such as ding( [] ), your first version is all that is required. No ... || () or some such is necessary.

    If, OTOH, you want to be able to call the routine with something else than an arrayref, e.g. no argument at all, none of your three variants really work.  All three would die with "Can't use an undefined value as an ARRAY reference" when run under use strict.   In this case, you probably want to explicitly test if the argument is a reference to an array:

    sub ding { my @foo = ref $_[0] eq "ARRAY" ? @{$_[0]} : (); ... }
Re: Dereference Empty(!) Array
by tangent (Parson) on Feb 20, 2012 at 19:09 UTC
    This is my attempt at decoding what's going on:
    1) @foo = the result of dereferencing $_[0] 2) @bar = the result of dereferencing $_[0] if $_[0] is true otherwise the result of dereferencing the empty array "()" 3) @jazz = the number of elements of the result of dereferencing $_[0] if that number is true (greater than 0) otherwise the empty array "()"
    So, depending on your arguments, both 2 and 3 may give unexpected results, and all three may cause problems if $_[0] is not an array reference
Re: Dereference Empty(!) Array
by Anonymous Monk on Feb 24, 2012 at 21:16 UTC

    my @array; my @newarray = @array || (); ### the same thing: my @new_array = @array; ## That is, if @array is undef, it is just extra code ## doing the test and assigning () to the new array... ## Just skip all that... they are the same op.