Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Perl Gotchas.

by EvdB (Deacon)
on Nov 20, 2003 at 14:51 UTC ( [id://308584]=perlquestion: print w/replies, xml ) Need Help??

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

I recently read this page on mysql gotchas and worried. I was glad that perl did not have this sort of gotcha.

Then I read About variable names and got worried again.

This morning I was burnt by this gotcha (code has been simplified):

use strict; # line 1 use warnings; # line 2 # line 3 my $value1 = 'foo'; # line 4 my $value2 = undef; # line 5 # line 6 if ( $value1 eq 'bar' ) { # line 7 print 'value1 is bar'; # line 8 # line 9 } elsif ( $value2 eq 'bar' ) { # line 10 print 'value2 is bar'; # line 11 # line 12 } # line 13
Because when you run it you get this from the warnings:
[evdb@desktop evdb]$ perl test.pl Use of uninitialized value in string eq at test.pl line 7.
But the 'undef in string eq' is on line 10! ( This took quite a while to debug ).

I ask you, what other perl gotchas are there out there that could bite me?

PS: I've looked at Regular Expression gotchas, Common Regex Gotchas and others from seaching for 'gotcha'.

--tidiness is the memory loss of environmental mnemonics

Replies are listed 'Best First'.
Re: Perl Gotchas.
by liz (Monsignor) on Nov 20, 2003 at 15:06 UTC
    I guess this could qualify as a bug, and definitely as a gotcha (one I must admit I never encountered myself). It goes back to 5.6.0 (when warnings.pm was introduced).

    I guess the entire if structure is seen as a single entity, so the line number refers to the line where the structure started. Well, at least it's better than not having any warnings at all. ;-)

    Liz

      The fact that all branches of an if test are seen as being the same line goes back way farther than that. I remember being annoyed with it with Perl 5.005_03 and it wasn't new then.

      However warnings.pm introduces some very annoying behaviour. It badly misused $Carp::CarpLevel with the result that their carps usually overflow the callstack and give them a cluck instead. But not always. If the error is deep in a stack of function calls, they may carp very near the surface. And certain kinds of import errors also occur at the wrong level.

      Which goes to show that $Carp::CarpLevel was a bad idea. Unfortunately fixing warnings to use the new @CARP_NOT array to get more sensible behaviour is a lot of work because of the fact that every last annoying detail of the current misbehaviour has been nailed down by tests. :-(

      A tip. Writing tests to nail down that code shall behave in an inconvenient way is a code smell. Fix the code to behave reasonably first and THEN write tests to guarantee that it won't change.

Re: Perl Gotchas.
by mpeppler (Vicar) on Nov 20, 2003 at 15:35 UTC
    This is a pretty common problem with parsers. I know that C parsers have the same sort of problem (see hardburn's comment, above), and Sybase's T-SQL parser's definition of a line is even more approximate, but you get used to it after a while.

    In perl a common problem that I've seen is a single missing }, which in a large file is sometimes reported as being missing at the end of the file even though there are a whole bunch of subroutines in the file, and the missing curly is somewhere in the middle...

    Michael

      This isn't actually a parser problem, it's an artifact of the language. It's perfectly legal to write subs within subs, so there's no good way for perl to determine when you meant to close off that first curly brace.
        You're quite right.

        But that still makes finding the offending missing curly difficult - which is what this thread is about, no? :-)

        Michael

      In perl a common problem that I've seen is a single missing }, which in a large file is sometimes reported as being missing at the end of the file
      Indeed, it would help if perl would point towards the opening { that is missing the closing brace, instead of pointing towards the end of the file, where the closing } is supposedly missing. I know where the end of the file is, thank you, I don't need anyone to point it out to me.

        A good trick in this case is to insert a } to the end of the file, and find its pair with your text editor. Most editors nowdays can do that (^G in joe; ^K[ in borland (unsure); % in vi; ^F^[b in emacs; } in less). Of course, this won't always work, it might jump to a different place than where the error is, but it's worth a try.

Re: Perl Gotchas.
by Zed_Lopez (Chaplain) on Nov 20, 2003 at 18:52 UTC

    See the Camel book ch. 24 and Perl Debugged ch. 4 for excellent coverage of Perl gotchas.

    I'd be lying if I said I'd never:

    • Put a comma after print $fh (where $fh is a filehandle)
    • Put a comma-separated list whose first element was a parenthetical expression immediately after print
    • Put a function call inside a hash's braces without parameters or parentheses (e.g. return $a{shift})
    • put a named constant before =>
    • failed to do the right thing when comparing floating point values
    • Failed to localize $_ before entering a while loop in a subroutine
    • Goofed on the ternary operator's precedence being higher than the named logical operators such that defined $a and $a ? 1 : 0 didn't do what I wanted
Re: Perl Gotchas.
by hardburn (Abbot) on Nov 20, 2003 at 15:08 UTC

    Perl's error messages suck. You get used to it after a while. use diagnostics can sometimes help. Just remember that the line reported in the error may not be the line that is actually causing a problem. This isn't a problem specific to Perl (I've heard stories of people getting hundreds of error messages from a C compiler due to a single missing semicolon), but it tends to happen more often in Perl compared to other languages.

    The reported error may have occured on that line or at some earlier point in the same block. I doubt that the error would have started outside the enclosing block, but I'm ready to be proven wrong on this.

    what other perl gotchas are there out there that could bite me?

    How many angels can dance on the head of a pin?

    ----
    I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
    -- Schemer

    : () { :|:& };:

    Note: All code is untested, unless otherwise stated

      "Perl's error messages suck."

      In this case, it sucks, but in general, I feel the opposite ;-) According to my own experience up to this point, Perl’s debug information meets my everyday needs.

      Perl's error messages suck.

      I have to admit though, every time I get a Segmentation Fault from some obtuse bug in our C codebase, I wish for Perl-type error reporting.

      :-)

       

      perl -le "print+unpack'N',pack'B32','00000000000000000000001010010001'"

Re: Perl Gotchas. (if( condition) { bug })
by grinder (Bishop) on Nov 20, 2003 at 17:31 UTC

    This one's a killer: you have an if that prints out a warning about an uninitialized values... but when you print out all the variables in the if's condition, they are all anything but undefined: Consider the following:

    #! /usr/local/bin/perl -w # 1 # 2 use strict; # 3 # 4 my $foo = shift || 'ok'; # 5 my $bar; # = undef # 6 # 7 print "foo contains [$foo]\n"; # 8 if( $foo eq 'nok' ) { # 9 print "foo is nok\n"; # 10 } # 11 elsif( $bar eq 'rat' ) { # 12 print "bar is rat\n"; # 13 } # 14 else { # 15 print "nothing\n"; # 16 } # 17
    When run, this produces:
    foo contains [ok] Use of uninitialized value in string eq at ifbug line 9. nothing

    This rather mind-boggling error (a variable with a defined value is undefined) is an error of a different kind. Yes, there's an unitialised variable, but it's not on line 9 as the error message would have you believe. It's actually on line 12.

    perl is complaining about $bar being undefined, but is getting its line numbers mixed up. Version 5.005_03 doesn't exhibit this behaviour, but 5.6 and 5.8 do. Which is yet another reason why I nearly lost my mind when I first encountered this problem.

    Moral: if you have a unexplainable error on a line containing an if, look at its elsifs and else, you just never know.


    just for the record, the above program was reformatted with perl -nle 'printf "%-30s # $.\n", $_'.

    update: sigh. This is what Liz is talking about. I started composing the answer and then Real Life intervened. Oh well.

    update 2: resigh. What a lunatic. I read this node, and then went and read About variable names, thought about what a hassle v-strings were, reminisced about pseudohashes... and forgot about the original gotcha expressed in this thread, which of course is exactly the same thing I just talked about. Oh well, I'll let it stand, but I feel like a right eejit.

    Here, then, is a minor gotcha that gets me from time to time. I'm a bit of an awk fan. If you can express something in awk, it's always more concise than Perl. But sometimes you want to do something trickier, so you recast it in Perl using the -a autosplit switch: as an example, print out the uids of all logins that start with 'p':

    awk -F: 'substr($1,0,1)=="p" {print $3}' /etc/passwd perl -F: -lane 'substr($F[0],0,1)eq"p" and print $F[2]' /etc/passwd

    Nine times out of ten, I forget to substract one from the awk variables to produce the @F offsets, and then wonder why my script doesn't work. But if you're not an awker, it's hardly likely to catch you.

    Apart from that, I can't think of any other gotchas :)

      just for the record, the above program was reformatted with perl -nle 'printf "%-30s # $.\n", $_'.

      For the record I formatted my code with pico, the middle mouse button, the arrow keys and plenty of the delete key. I feel slightly inadequate now... ;-)

      --tidiness is the memory loss of environmental mnemonics

        cat -n is where it's at.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://308584]
Approved by broquaint
Front-paged by broquaint
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (8)
As of 2024-04-18 14:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found