2

Initially, my code looked like this:

my @departments = @{$opts->{'d'}} if $opts->{'d'};

I wanted to refactor the in-line if statement according to Perl Best Practices, so now I've got the following code:

my @departments;
if( $opts->{'d'} )
{
    @departments = @{$opts->{'d'} };
}

$opts is just a hash reference that could possibly have an array ref as the value of a key.

I'd like to do something like the following to keep the code on one line:

my @departments = $opts->{'d'} ? @{$opts->{'d'}} : undef;

But obviously that will just put one element into @departments with value undef.

The reason I'm performing this action in this way is because I later want to be able to check

if( @departments )
{
    my $department_string = join( q{,}, @departments );
    $big_string . $department_string;
}

to dynamically add to a string.

s_dolan
  • 1,196
  • 1
  • 9
  • 21
  • 2
    `my @departments = map $_, @{ $opts->{d} };` :) No, don't use that, it's a weird way of doing `my @departments = @{ $opts->{d} //= [] };` – ikegami Jul 31 '15 at 21:29

3 Answers3

7

Doing this:

my @departments = $opts->{'d'} ? @{$opts->{'d'}} : undef;

is the same as

my @departments = $opts->{'d'} ? @{$opts->{'d'}} : (undef);

which if $opts->{d} is false will assign a single element, undef, to the array @departments. You don't want an array that contains a single element. You want an empty array.

So, what you want to do is assign an empty list to @departments, like so:

my @departments = $opts->{'d'} ? @{$opts->{'d'}} : ();

One other thing: Your title says "conditionally instantiate a new Perl array", and really what we're doing is conditionally filling it. It's instantiated when you say my @departments.

Andy Lester
  • 91,102
  • 13
  • 100
  • 152
  • Right, when I say "conditionally instantiate", I mean reproduce the following behavior: `my @departments = @{$opts->{'d'}} if $opts->{'d'}` – s_dolan Aug 01 '15 at 02:11
  • @s_dolan Using `my` with a statement modifier is [undefined behavior](http://perldoc.perl.org/perlsyn.html#Statement-Modifiers)...don't do it! "The value of the `my` variable may be `undef`, any previously assigned value, or possibly anything else. Don't rely on it. Future versions of perl might do something different from the version of perl you try it out on. Here be dragons." – ThisSuitIsBlackNot Aug 01 '15 at 04:41
  • @ThisSuitIsBlackNot Thanks so much! I will avoid doing that in my code from this point onwards. – s_dolan Aug 02 '15 at 12:02
4

This result in @departments being set to an empty array if the condition fails.

my @departments = $opts->{'d'} ? @{$opts->{'d'}} : ();
ikegami
  • 367,544
  • 15
  • 269
  • 518
stevieb
  • 9,065
  • 3
  • 26
  • 36
  • 1
    if you want to avoid the repetition: `map { $_ ? @$_ : () } $opts->{d}` or `map @$_, grep $_, $opts->{d}` – ikegami Jul 31 '15 at 21:32
  • Thanks. I don't know why it didn't dawn on me to use `()` instead of `@{[]}`. – stevieb Jul 31 '15 at 21:51
  • The slimmed down answer is definitely neat, but as this is in a large system where many developers (and some new to Perl) will be digging in, I'm trying to keep it more readable. I'd also suggest using the [English](http://search.cpan.org/~rjbs/perl-5.22.0/lib/English.pm) module to rename your `$_` to `$ARG`. – s_dolan Aug 01 '15 at 02:23
2

I would use

my @departments = @{ $opts->{d}||[] };

If $opts->{d} does not exist, it is not true, thus perl looks for the right side of '||' and finds the empty arrayref, which is then cast into an empty list.

It is not really that different from explicitly checking with if or the '?' operator, as the above answer, but I find it clearer and less distracting to read in code, especially since it is only one line.

Consider alternatively:

$opts->{d} ||= [];
my @departments = @{$opts->{d}};

That would first set an empty arrayref, then cast as array, and would basically do the same thing ( unless you wanted to repeatedly cast into an array, then this method would save you from typing || [] repeatedly ).

I hope this helps, I have seen the notation I suggested often for casting arrays / hashrefs ( my %hash = %{ $hash||{} }; )when uncertain whether it has been set.

bytepusher
  • 1,568
  • 10
  • 19