Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling

default values for lists

by pike (Monk)
on Sep 17, 2002 at 15:00 UTC ( #198502=perlquestion: print w/replies, xml ) Need Help??
pike has asked for the wisdom of the Perl Monks concerning the following question:

I often use default values for scalar variables, e. g.

$val = $x || $default

Now I tried this for lists, but it doesn't work - or, to be precise, it works only if the first list is empty, because otherwise the first list is interpreted in scalar context:

@a = (); @b = qw (one two three); @c = qw (four five); @d = @a || @c; #gives ('four', 'five') - OK @d = @b || @c; #gives ('3') - yikes!

Can I inhibit the interpretation of the first list as scalar? Or is the only way to get the desired behaviour:

@list = @a; @list = @default unless @list;

Thanks for your suggestions,


Replies are listed 'Best First'.
Re: default values for lists
by fglock (Vicar) on Sep 17, 2002 at 15:03 UTC
    try this:  @d = @a ? @a : @c;
      OK, maybe I should have given more context: I was trying to strip of the ending of words, do something with the words and put the ending back on, like this:

      my ($end) = $word =~ /(e?s)$/ || (''); ... #do something with $word $word = "$word$end";

      If the word does not end in s/es, I get a warning about uninitialized variables where I append $end - which I wanted to avoid.

      I thought about the ternary, but I don't want to evaluate the regex twice.

      I simplified the problem because IMO it boils down to the question if I can enforce list context on the part before the ||. But maybe I oversimplified it.

      Thanks anyway for the suggestion.


        Ah, ok. Try this:

        ($begin, $end) = $word =~ /(.*?)(es|s|)$/;
        Then I'd say my $end = $word =~ /(e?s)$/ ? $1 : '';

        Makeshifts last the longest.

Re: default values for lists
by Elgon (Curate) on Sep 17, 2002 at 15:09 UTC

    Hi pike,

    You could try using the trinary operator...

    @d = @a ? @a : @c;

    In the example given, if @a returns true (in scalar context ie. has a nonzero length) then it is copied into @d, otherwise the contents of @c are copied into @d.

    Update: Arrgh, fglock beat me to it!

    "Rule #17 of Travel: Never try and score dope off Hassidic Jews while under the impression that they are Rastafarians."
           - Pete McCarthy, McCarthy's Bar

Re: default values for lists
by RMGir (Prior) on Sep 17, 2002 at 15:12 UTC
    There are a few options I can see. If it's completely "either @a or @default", or if you want all of @a, and fill in with the first few from @default if @a is short, then you could do this:
    As an alternative, you could do:
    @list=map {$_>$#a ? $default[$_] : $a[$_] } 0..$#default;
    It's a lot easier to do default values if you use hashes, though.
Re: default values for lists
by blokhead (Monsignor) on Sep 17, 2002 at 17:42 UTC
    Assuming I've not misintepreted your question, I'd lean towards a solution something like this:
    my @defaults = qw/one two three four five/; my @a = qw/un deux trois/; $a[$_] ||= $defaults[$_] for (0 .. $#defaults); print "@a\n"; # prints "un deux trois four five"
    Again, if you're looking for a completely either-or approach to the two lists, then the aforementioned trinary operator is probably the best choice. If you want to take from @a or @defaults on a per-element basis, then the trinary operator won't give you the desired results -- you'll need to use an approach like mine or RMGir's above.


Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://198502]
Approved by Elgon
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (3)
As of 2018-05-20 13:46 GMT
Find Nodes?
    Voting Booth?