[comp.sources.bugs] Perl and $#

friedman@chekov.UU.NET (Barry Friedman) (12/28/89)

I am running perl v3.0 patchlevel 8 on an hp9000/840 system and
am getting some strange results using the $# variable. 
Conversions are inconsistant and linefeeds disappear.

Here's my test program:

	#!/usr/local/bin/perl

	$a = 1/3;
	print $a, "\n";
	print "$a\n";

	$#="%.3g"; # set numeric width

	# note lack of linefeeds in output
	print "$a\n";
	print "$a \n";
	print $a, "\n";  # this one puts out a linefeed

	#note incorrect conversion
	print "a= $a \n";

	print "$a" . "\n";  # no linefeed here
	print "\n";
	print $a,  "\n";    # but this puts one out
	print "a= $a \n";

And the output:

	0.33333333333333331
	0.33333333333333331
	0.3330.3330.333
	a= 0.33333333333333331 
	0.333
	0.333
	a= 0.33333333333333331 

Is this a bug or am I missing something?
-- 
Barry Friedman              UUCP: ...!uunet!chekov!friedman

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (12/29/89)

In article <1630@bnr-rsc.UUCP> chekov!friedman@uunet.UU.NET (Barry Friedman) writes:
: I am running perl v3.0 patchlevel 8 on an hp9000/840 system and
: am getting some strange results using the $# variable. 
: Conversions are inconsistant and linefeeds disappear.
: 
: Here's my test program:
: 
: 	#!/usr/local/bin/perl
: 
: 	$a = 1/3;
: 	print $a, "\n";
: 	print "$a\n";
: 
: 	$#="%.3g"; # set numeric width
: 
: 	# note lack of linefeeds in output
: 	print "$a\n";
: 	print "$a \n";
: 	print $a, "\n";  # this one puts out a linefeed
: 
: 	#note incorrect conversion
: 	print "a= $a \n";
: 
: 	print "$a" . "\n";  # no linefeed here
: 	print "\n";
: 	print $a,  "\n";    # but this puts one out
: 	print "a= $a \n";
: 
: And the output:
: 
: 	0.33333333333333331
: 	0.33333333333333331
: 	0.3330.3330.333
: 	a= 0.33333333333333331 
: 	0.333
: 	0.333
: 	a= 0.33333333333333331 
: 
: Is this a bug or am I missing something?

First, allow me to quote the manual page entry for $#:

     $#      The output format for printed numbers.  This vari-
             able is a half-hearted attempt to emulate awk's OFMT
             variable.  There are times, however, when awk and
             perl have differing notions of what is in fact
             numeric.  Also, the initial value is %.20g rather
             than %.6g, so you need to set $# explicitly to get
             awk's value.  (Mnemonic: # is the number sign.)

Note first that it is the *output* format.  That is why there is
no conversion inside the string "a= $a \n".  Double quote interpretation
has nothing to do with output.  In a print statement, each element
of the LIST is evaluated separately for numberhood, and there aren't
any number that start out "a=".

Second, perl's notion of what looks like a number allows for trailing
whitespace, including newlines.  This is why the newlines are getting
eaten.  It could be argued that this shouldn't be so.  It can also be
argued that it should, since there are a number of situations in perl
where a trailing newline *should* be ignored.  In any event, the way
it's currently set up, if perl thinks the field is a number, any leading
or trailing whitespace is discarded before converting the string to
a number to feed to the $# format.

Third, notice the disclaimer "half-hearted".  $# is an admitted kludge
to facilitate awk-to-perl translation.  In general you'll be better
off using printf with an explicit format.  If you really want to use $#,
find an idiom that works and stick with that.

[Redirecting followups to comp.lang.perl.]

Larry Wall
lwall@jpl-devvax.jpl.nasa.gov
"So many programs, so little time..."