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

I am trying to understand how $# works... would love it if someone could explain why I get these weird results: Am I using $# wrong?
When more than 1 variable is enclosed inside print string, the $# format is ignored... as are strings and newlines... ENV: Win32 / perl, v5.8.0 built for MSWin32-x86-multi-thread
use strict; $# = '$%.2f'; #Money format my $amount = 123.2353; my $taxes = $amount * 6 / 100; print "$amount - $taxes = ", $amount-$taxes; print "\n$amount -", " $taxes = ", $amount-$taxes; print "\n$amount -", $taxes," = ", $amount-$taxes; # spaces are ignored! - newline is ignored! print "\n$amount ","-", $taxes," = ", $amount-$taxes; print "\n"," $amount ","-", $taxes," = ", $amount-$taxes; print "\n$amount \-", $taxes," = ", $amount-$taxes; #output #123.2353 - 7.394118 = $115.84 #123.2353 - 7.394118 = $115.84 #123.2353 -$7.39 = $115.84$123.24-$7.39 = $115.84 #$123.24-$7.39 = $115.84 #123.2353 -$7.39 = $115.84
Thanks, James

Replies are listed 'Best First'.
Re: Odd behavior of $#
by Fletch (Bishop) on Feb 19, 2003 at 18:53 UTC

    $# applies only to print itself doing the conversion. Interpolating the variable into a string doesn't bring it into play.

    Also note that $# is deprecated and it's better to explicitly run through sprintf than depend on it.

      $# applies only to print itself doing the conversion. Interpolating the variable into a string doesn't bring it into play.
      Exactly! Which is why this line works:
      print "\n","  $amount   ","-", $taxes," = ", $amount-$taxes;

      Also note that $# is deprecated...
      Which JamesNC would have known if he had enabled warnings.

      ... and it's better to explicitly run through sprintf than depend on it.
      Is there a way to tell sprintf to add a dollar sign? Or do you have to explicitly append it? Like:
      my $net = '$'.sprintf("%.2f", $amount - $taxes);

        Right, that case works because print itself is doing the conversion. If $# is set then each element passed to print is looked at to see if it can be converted to an IV or an NV. If it can, it's formatted using $#. Spaces don't matter when considering if it's numeric, so "  1.23456  " doesn't look any different than a numeric 1.23456 (and in fact the spaces will be stripped before the conversion is done).

        $ perl -le '$#="%0.2f";$a=1.2345;print "|", " $a ", "|";' |1.23|

        However in the other cases, there's more than spaces and digits (and decimals, and whatnot that perl recognizes as a numeric) so it's not seen as an IV or NV and not treated to the $# munging. See Perl_do_print in doio.c for the complete skinny on what exactly happens.

        Is there a way to tell sprintf to add a dollar sign?
        Sure, just: my $net = sprintf '$ %.2f', $amount - $taxes;You can put whatever you like in the format string.

        For more complicated things, you can try Number::Format. It's a little heavyweight for my taste, but it works.

Re: Odd behavior of $#
by hv (Prior) on Feb 19, 2003 at 19:18 UTC

    I think you're coming up against a bit of perl DWIMery, that it decides a string "looks like a number" if it has only whitespace around the number. You can work around it by not doing that (eg by having "\n$amount -"), but you are best off just using printf and avoiding the (deprecated) $# variable:

    printf "\n%s - %2f = %.2f", $amount, $taxes, $amount - $taxes;

    Hugo
      Thanks all.. I knew how to do this using sprintf and printf, I just wanted to know why it acted wacky. Perhaps this is why it is deprecated??