sub call not getting params??

Tom Phoenix rb-pdx-pm at redcat.com
Wed Jul 3 21:41:35 CDT 2002


On Wed, 3 Jul 2002, Russ Johnson wrote:

> I have this in a script I'm writing:
>
> 		foreach $tag ( @tags ) {
> 			if ( "$$tag" ) {

Whenever I see unnecessary(?) quote marks like that, I always have to
wonder whether the author thought they were functional. And, if so, what
could their function possibly be?

You may be thinking that they're harmless, and functionally they
(probably) are. But, even if they have no other shortcomings, they're
extra typing for you, and anyone else who has to look at this code has to
spend extra time thinking about them.

> 			$writer->startTag("$tag");
> 				$writer->characters("$$tag");
> 			$writer->endTag("$tag");
> 			}
> 		}

What's up with this indentation? I know, it sounds like I'm complaining
about something that has nothing to do with functionality. But in general,
the regularity of a perl program's indentation is directly proportional to
the author's comprehension. So, indent properly, and you'll fool 'em all!

Ah, I see it now: You're indenting everything between startTag and endTag.
That's cool. It's just the curly braces that threw me off. Or, perhaps I
should say, the code in the curly braces isn't indented further than the
braces themselves.

And I see you using $$tag. That implies that $tag is a reference to a
scalar. Okay. But then what does "$tag" mean? I'm coming back to those
quote marks for good reason now: If $tag is a reference, then "$tag" is a
_string_ like "SCALAR(0x1234FEDC)". That's not (necessarily) useless, but
it sure makes me wonder what you're doing with it. (Or maybe $tag is an
object with overloaded stringification? If that's it, then the quote marks
are intentional and not useless.)

> Which works fine. However, the part inside the if statement is repeated
> elsewhere, so I tried this:
>
> 		foreach $tag ( @tags ) {
> 			if ( "$$tag" ) {
> 			&writer( "$tag", "$$tag" );
> 			}
> 		}

Hmmm... You're passing that stringified reference as the first parameter.
And I have to wonder whether you'll always be using
the-same-thing-dereferenced as the second argument. Shouldn't you simply
pass $tag, and let &writer() do the dereference as needed?

> sub writer {
>
> 	$writer->startTag("$_[0]");
> 		$writer->characters("$_[1]");
> 	$writer->endTag("$_[0]");
>
> }

What's $writer at this point in the program? Some object, it seems. And
from the terminology, you're probably using HTML::Parser or a similar
module. (Good for you, for not trying to parse HTML directly!) But if
$writer is a global (or a file-scoped my() variable), you should probably
say so in a comment at the start of that sub.

> When I run this, I get value undefined in line ### where line ### is the
> line with $_[0] in it. So why are my parameters not making it to writer?

Maybe it's $writer that's undefined. That's what I'd suspect. Did you
initialize it to your parser object (or whatever)? Is it still in scope at
the time of this sub's declaration? (You are using 'strict', aren't you?)
Double check that it's not undef by adding a line like this at the top of
the sub, just after your comment about the global-ish $writer:

    die "Oops: \$writer is undef" unless defined $writer;

Hope this helps!

--Tom Phoenix

TIMTOWTDI



More information about the Pdx-pm-list mailing list