Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Re: Breaking The Rules

by Unanimous Monk (Sexton)
on May 30, 2006 at 22:17 UTC ( [id://552643]=note: print w/replies, xml ) Need Help??


in reply to Breaking The Rules

This may be slightly off topic, but in the spirit of investigating the "Always use warnings" mantra, is there really any benifit to writing
use warnings; my $var=1; print $var if defined $var;
over
use warnings; my $var=1; print $var unless $var eq undef;
other than to avoid the warnings? I'm still reluctant to "use warnings", simply because it seems to nitpick my syntax more often than provide a legitimate warning.

Replies are listed 'Best First'.
Re^2: Breaking The Rules
by GrandFather (Saint) on May 30, 2006 at 22:32 UTC

    I would write:

    use warnings; my $var=1; print $var;

    Why the test? If $var is undef something much more serious is going on and I want to know about it.

    Yes, I know this is a trivial example and you imply that there may be legitimate situations in which $var is undef. However I'm suggesting that if $var is undef when you are about to print its contents, then there is a flaw in the code. It may be as trivial as not having provided a default value, but providing the default value is important - it says to the reader that you have thought about the special case of the variable contents haven't been changed.

    BTW, your second version is needlessly convoluted and will generate a warning (two if $var is undefined). KISS


    DWIM is Perl's answer to Gödel
      However I'm suggesting that if $var is undef when you are about to print its contents, then there is a flaw in the code.

      Its seldom a 'flaw in the code' if you need to check whether something has been defined. It could be a flaw from, say, user supplied input and your code needs to differentiate between data that was missing entirely (undef) and an empty string or 0.

      while (<FILE1>) { $var = GetVar($_); }; if ($var eq undef) { die "File provided doesn't include var!\n"; }
      You can't rely on warnings to tell you var didn't exist in the file, and you have no control over whether var gets defined.

      Also, there are benefits to "define when needed" if you have a complex set of processing which may or may not require a particular variable in numerous places and its impossible to predict which loop is going to need the variable first, if at all. Rather than needlessly calculating it before starting, just check for undef wherever you use it.

      There are countless legitimate reasons why you'd want to check whether a variable has been defined, and its not a rare occurrence.


      BTW, your second version is needlessly convoluted and will generate a warning (two if $var is undefined). KISS

      That's the point of my example; the fact that it throws a warning (or two), and its not needlessly convoluted (although the opinion of convolutedness apparently varies). In fact, it provides more symmetry if your doing something like

      if ($var eq undef) { ... } elsif ($var eq '') { ... } elsif ($var eq 'foo') { ... };

        I agree absolutely that there are often times when you need to check to see if something is defined in Perl. I was questioning the use of the test in a context where it looks like the variable should have been validated long ago - a rather bold interpretation of the example code I agree.

        The important point here is to distinguish between cases where it is expected that a variable may be undefined as a result of previous processing (defined should be used to test that), and where a variable is undefined because of a flaw in previous processing - in which case use warnings catches the problem as early as possible and is extremly useful.

        That's the point of my example; the fact that it throws a warning (or two)

        In that case your example is gratuitiously idiosyncratic. The language provides a clean way of testing for a defined value. Why bend over backwards to avoid using defined?

        While Its seldom a 'flaw in the code' if you need to check whether something has been defined, it is almost always a flaw in the code if use warnings generates an undefined used type warning. Comparing with undef is flawed, if only because you lose the virtue of turning on warnings.


        DWIM is Perl's answer to Gödel
        You can't rely on warnings to tell you var didn't exist in the file, and you have no control over whether var gets defined.

        Not true:

        while (<FILE1>) { $var = GetVar($_) || $some_reasonable_default; };
        $var is now guaranteed to have a defined value on every iteration, regardless of the file's contents. Granted, there are cases where there is no reasonable default, but, as the programmer, I do still have control over whether $var is defined or not, should I choose to exercise it.
        if ($var eq undef) { ... } elsif ($var eq '') { ... } elsif ($var eq 'foo') { ... };

        As noted several times, 'eq' isn't "equals" it is "string equals" (and '==' is "number equals"). If you want to compare to 'undef', then you want 'given' (or 'when' or '~~', Perl6isms that'll appear in Perl5 soon enough -- I'd say more but searching for "given" is pretty useless, since I see patches to add them already being applied).

        - tye        

Re^2: Breaking The Rules
by Anonymous Monk on May 31, 2006 at 20:00 UTC
    Your two ways of testing undef don't actually do the same thing. if defined $var will execute your statement if $var is defined. unless $var eq undef will execute your statement if $var is undef, the empty string, or something else that will stringify to the empty string. Try the following code snippet to see for yourself:
    my $var = undef; print "Undefined!\n" if $var eq undef; $var = ''; print "Undefined again!\n" if $var eq undef;
    This happens because the "eq" operator stringifies both of its arguments, and undef stringifies to the empty string. The warning doesn't exist just to critique your syntax... it's warning you of a danger that your code might not be doing exactly what you think it is.
      Hmmm, your right. That’s not how I thought it was working, but it makes sense that it works that way.

      Learn something new everyday! (I apologies if this is what GrandFather was trying to point out, and I was too obtuse to realize it) :)

Re^2: Breaking The Rules
by spiritway (Vicar) on Jun 02, 2006 at 03:31 UTC

    The thing about use warnings; is that it helps you to avoid subtle, sneaky errors that you would otherwise have a very difficult time tracking down. I'll gladly put up with a few spurious warnings, versus spending many hours of head-banging debug time trying to find where I slipped up. For me, use warnings; has paid for itself many times over.

    As is so often the case, YMMV. I've never encountered anything like the situation you mention. Perhaps I'm not sufficiently advanced; perhaps it's just coding styles. If I ran into problems more often, I might agree with you and stop using warnings. To date, though, this nit-picky little pragma has saved me much aggravation and gnashing of teeth, muttering evil phrases, and all that fun stuff we're so good at.

Re^2: Breaking The Rules
by runrig (Abbot) on May 31, 2006 at 21:09 UTC
    is there really any benifit to writing...(snip)...other than to avoid the warnings?

    Yes, the former is more clear in its intent, the latter is a longer and more obfuscated way of writing print $var unless $var eq '' (update: and even that may as well be just print $var ...printing an empty string shouldn't make a difference anyway...though I assume this is just a simple example and you could have, e.g., print "blah blah $foo blah" unless defined $foo)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://552643]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (7)
As of 2024-04-18 13:59 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found