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
"whole-dollar" part is preserved.  For more information on "printf", check out
"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
 Seattle Perl Users Group (SPUG) Home Page: http://www.halcyon.com/spug/
 SUBSCRIBE/UNSUBSCRIBE: Replace ACTION below by subscribe or unsubscribe
        Email to majordomo at pm.org: ACTION spug-list your_address





More information about the spug-list mailing list