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

# this works: my $default = '""'; # double quotes to be inserted when my $name = ''; # is empty my $insert = $empty || $default; # insert this print "name = $insert\n";

The result is either: `name = ""` or `name = fred`, when $name = 'fred'. So far so good.

But how do I get rid of the spurious variable $insert? I expected something like this:

print "name = ${\ $name || $default }\n"; # dosen't work!!

to work, but, results in `name =` missing the "". ie the code interpolation is null when $name = ''. Does || mean something different in a code interpolation?

Am I missing some subtlety? :-(

Thanks in advance.

Replies are listed 'Best First'.
Re: Interpolation requires a spurious variable. Why?
by AnomalousMonk (Archbishop) on Sep 23, 2009 at 22:03 UTC
    This is a precedence problem. See Symbolic Unary Operators in perlop.

    When the expression
        \ $name || $default
    is evaulated, the sub-expression  \ $name has highest precedence. A reference is always true, so the second sub-expression (i.e., the  $default scalar) is never evaluated.

    I would prefer the approach given by moritz above, but if you absolutely must do code interpolation within a string, here are a couple of approaches:

    >perl -wMstrict -le "my $default = q{''}; for my $name ('', 'fred') { print qq{name = ${ \ do { $name || $default }}}; print qq{name = @{[ $name || $default ]}}; } " name = '' name = '' name = fred name = fred
      The most straightforward way to resolve precedence issues is to add parens.
      ${\( $name || $default )}
      why not  print " ${\ ($name||$default) }" ???

      Works fine for me! 8)

      Cheers Rolf

      I missed the parenthesization approach of ikegami and LanX, but my personal preference (after moritz's approach, of course) would be  "@{[ ... code ... ]}" temporary array interpolation. This is probably more expensive computationally, but it appeals to me as 'cleaner' code.
        Why should it be cleaner? It's just another case and depends on the context you want for the inner code.

        Instead of a scalar you require a list to be interpolated into a string!

        (which also involves the extra complication of setting $" appropiately.)

        Cheers Rolf

        It's not so much that it's "cleaner". The reason I'd prefer it myself is that it's idiomatic. It's a fairly well-known construct. Even if you don't use it yourself, it's worth knowing because it's something you'll probably see in others' code.

        I don't think the same is as true of "${\()}" -- I can't recall ever seeing that before today.

Re: Interpolation requires a spurious variable. Why?
by moritz (Cardinal) on Sep 23, 2009 at 21:32 UTC
    printf "name = %s\n", $name || $default;

    You can also use string concatenation or sprintf.

    Perl 6 - links to (nearly) everything that is Perl 6.
Re: Interpolation requires a spurious variable. Why?
by ikegami (Patriarch) on Sep 24, 2009 at 14:05 UTC
    Cleaner alternatives:
    $name = ...; $name ||= '""'; print "name = $name\n";
    $name = ...; printf "name = %s\n", $name || '""';