# SPUG: Rebuked...

Ken McGlothlen mcglk at serv.net
Tue Jan 4 16:30:44 CST 2000

```"Steve Laybourn" <otter101 at hotmail.com> writes:

| >	sub Cur {
| >	    my( \$ix ) = shift;
|
| ---Let local variable \$ix equal the first element of the default array @_,
| which in this case also equals \$_. Hmmm, clever, that. How would you handle
| more than one element going in to the array? @_[0], at _[1], etc.?

Well, if you wanted to process each of these in a list, and return a list of
values, you'd write something like:

sub Cur {
my( @ix ) = ();
foreach( @_ ) {
\$_ = sprintf( "%.2f", \$_ );
1 while s/(.*\d)(\d\d\d)/\$1,\$2/g;
push( @ix, "\\$\$_" );
}
return( @ix );
}

Make sense?

| ---This bit puzzles me a little. I understand the rounding function
| represented by the "%.2f" (you described it earlier, I'm looking into that
| further), but wouldn't assigning the result to \$ix write over the current
| value of \$ix, thusly eliminating the whole dollar part of \$ix?

Er, no.  The "%.2f" translates something like "29330.5051" to "29330.51"; the
"man printf" on any Unix system.  If you don't have a Unix system handy, let me
know and I'll mail you the page.

| >	    1 while \$ix =~ s/(.*\d)(\d\d\d)/\$1,\$2/g;
|
| ---OK, I really had to think this one out, but here goes:
| ---If the regular expression evaluates to true, then do the operation. Hmmm,
| I had wanted to work with up to nine digits and two decimal places, so
| would:
| ---1 while \$ix=~ s/(.*\d)(\d\d\d)(\d\d\d)/\$1,\$2,\$3/g;
| ---be more or less correct? The "1 while ..." statement is completely new to
| me. A long time ago I would have thought it to be a label or a line number.

Well, it's a trick.  This could also be written

while( \$ix =~ s/(.*\d)(\d\d\d)/\$1,\$2/g ) {
1;
}

The "1" simply returns the value "1" (or true), but doesn't assign it to
anything; it's just a syntactic placeholder that doesn't put too much of a load
on the system.  The real work is done by the while statement, which goes until
the match fails.  Let's assume that \$ix is currently 9872349873.23.  This is
what happens.

*	The first match becomes:

\$1 = 9872349
\$2 = 873

Why?  Well, the .* is as greedy as possible, and \$1 must end with a
digit, so it's going to grab as much as it can.  \$2 prevents it from
grabbing the remaining three digits.  This means that "9872349873.23"
becomes "9872349,873.23".

*	The second match becomes:

\$1 = 9872
\$2 = 349

Why?  Well, same thing as before, except that we have to remember that
the comma is not a digit.  So this also inserts a comma in the right
place.  One more iteration picks up the comma after the 9, and then on
the next iteration, the match fails and the loop ends.

| Again, I apologize for not being terribly good at Perl

Hey, it's not all *that* easy.  But there's a lot of power in Perl, and it's
often worth looking around for a more convenient way of doing things rather
than taking the approach you might use in, say, C or FORTRAN.  Perl has a very
natural way of working with text and numbers, and there's no better way to
learn than by posting ineffecient code in front of a bunch of amazingly picky
people.  :)

| Thanks again. I'll be sure to irritate you again very soon.

No irritation registered.  :)

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
POST TO: spug-list at pm.org        PROBLEMS: owner-spug-list at pm.org