Silvio Mayolo Silvio Mayolo - 1 year ago 44
Perl Question

Dereferencing Conditionally in Perl

I have a scalar that may or may not be a reference to an array. If it is a reference to an array, I would like to dereference it and iterate over it. If not, I would like to treat it as a one-element array and iterate over that.

my $result = my_complicated_expression;
for my $value (ref($result) eq 'ARRAY' ? @$result : ($result)) {
# Do work with $value

Currently, I have the above code, which works fine but feels clunky and not very Perlish. Is there a more concise way to express the idea of dereferencing a value with fallback behavior if the value is not what I expect?

Answer Source

Being perl, there's going to be several answers to this with the 'right' one being a matter of taste - IMHO, an acceptable shortening involves relying on the fact that the ref function returns the empty string if the expression given it is scalar. This means you don't need the eq 'ARRAY' if you know there are only two possibilities (ie, a scalar value and an array ref).

Secondly, you can iterate over a single scalar value (producing 1 iteration, obviously), so you don't have to put the $result in parentheses in the "scalar" case.

Putting these two small simplifications togeather gives;

use v5.12;

my $result1 = "Hello World";
my $result2 = [ "Hello" , "World" ];

for my $result ($result1, $result2) {
    for my $value ( ref $result ? @$result : $result) {
        say $value ;

which produces;

Hello World

There's likely to be 'fancier' things you can do, but this seems a reasonable compromise between being terse and readable. Of course, YMMV.