Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Help! My variables are jumping off a cliff!

by oko1 (Deacon)
on Feb 26, 2012 at 03:29 UTC ( [id://956175]=perlquestion: print w/replies, xml ) Need Help??

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

#!/usr/bin/perl # Right, no warnings. use strict; my $x = 1; # Variable declaration my $x = 10; # Variable suicide! print $x;
Output:
10

OK... isn't preventing this the entire point of "strict 'vars'"? (If not, then I've been seriously confused about it for a long time.)

-- 
I hate storms, but calms undermine my spirits.
 -- Bernard Moitessier, "The Long Way"

Replies are listed 'Best First'.
Re: Help! My variables are jumping off a cliff!
by BrowserUk (Patriarch) on Feb 26, 2012 at 04:25 UTC

    What's so hard to understand?

    Strict ensures that variables are declared:

    C:\test>perl -Mstrict -E"$x = 1; $x = 10" Global symbol "$x" requires explicit package name at -e line 1. Global symbol "$x" requires explicit package name at -e line 1. Execution of -e aborted due to compilation errors. C:\test>perl -Mstrict -E"my $x = 1; my $x = 10"

    Warnings will tell you if you did it twice at in the same scope:

    C:\test>perl -Mstrict -wE"my $x = 1; my $x = 10" "my" variable $x masks earlier declaration in same scope at -e line 1.

    Declaring a variable twice isn't an error, just unnecessary, hence a warning rather than a fatal error.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

    The start of some sanity?

      Declaring a variable twice isn't an error, just unnecessary

      Declaring a variable twice in the same scope is indeed an error - and of exactly the same type as 'strict' is supposed to prevent. Perl may not throw a warning about it as a default behavior, but that does not make it not an error. Is there ever a situation in which declaring a variable twice in the same scope is useful? Conversely, is there ever a time when doing so will not cause problems?

      It seems to me that reasonable answers to both of the above questions imply that this should indeed be a feature in "strict" - if not in Perl itself. It would have rather obvious positive effects, and no negative ones that I can think of.

      -- 
      I hate storms, but calms undermine my spirits.
       -- Bernard Moitessier, "The Long Way"
        Declaring a variable twice in the same scope is indeed an error...

        my does two things. During compilation, it creates an association between a variable name and its appropriate lexical scope. During runtime, it initializes the appropriate storage for that variable.

        The strict pragma only cares about the former; the documentation has long stated:

        This generates a compile-time error if you access a variable that wasn't declared via "our" or "use vars", localized via "my()", or wasn't fully qualified.

        While you may be right that strict should warn about double declaration, strict 'vars' only concerns itself with an idempotent operation. You can't create that compile-time association more than once in the same scope because that association is an either-or concern.

        With that said, you can't unilaterally assume that all instances of the double-declaration have unintended runtime consequences. Those consequences are also well established and long understood. I can imagine code which does this deliberately.

        That's not my particular style, but not everything I find confusing is (nor should it be) an error.


        Improve your skills with Modern Perl: the free book.

        Declaring a variable twice in the same scope is indeed an error ...

        By who's definition? Certainly not Perl's. Or strict's.

        and of exactly the same type as 'strict' is supposed to prevent.

        And yet -- it doesn't. Which could mean one of two things:

        1. The strict module has had a bug all these years and nobody noticed until you did.
        2. You've misunderstood.

        I'll let you decide which you want to believe.

        And while you do that, I'll continue to believe the evidence of the implementation, and bet you that nothing you say or do will make it change in the future.


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

        The start of some sanity?

        A reply falls below the community's threshold of quality. You may see it by logging in.

        Is there ever a situation in which declaring a variable twice in the same scope is useful? Conversely, is there ever a time when doing so will not cause problems?

        Yes - when a variable is no longer needed, then there's no harm in redeclaring it and using it for a different purpose.

        For example, imagine the following test script:

        use Test::More; use strict; no warnings; diag "Testing that 'uc' works."; plan tests => 3; my $result = uc 'foo'; is $result, 'FOO'; my $result = uc 'bar'; is $result, 'BAR'; my $result = uc 'baz'; is $result, 'BAZ';

        Certainly different variables could be used for each test, or the my could be dropped from the second and third tests, but why should Perl insist upon it. The code above is perfectly clear, and runs fine.

        Declaring a variable twice in the same scope is indeed an error -

        No, it's not. The following code works just fine:

        my $x = 1; say $x; my $x = 2; say $x;
Re: Help! My variables are jumping off a cliff!
by tangent (Parson) on Feb 26, 2012 at 04:05 UTC
    strict vars will only prevent declarative suicide, not kamikaze coding :)

      Could you define "declarative suicide", please?

      I'm also not very clear on why you'd consider the problem that I'm demonstrating as an example of "kamikaze coding". Imagine a script in which you've already declared a lexically-scoped $foobar; a couple of hundred lines later, you decide that you need a new variable name, and $foobar seems like a reasonable thing. Create it, and - presto - you've destroyed the previous one. Is that "kamikaze coding"? Or is it a language problem?

      #include <stdio.h> int main(void) {int x = 1; int x = 10; printf("%d\n", x);}
      ben@feynman:/tmp$ cc x.c x.c: In function ‘main’: x.c:3:33: error: redefinition of ‘x’ x.c:3:22: note: previous definition of ‘x’ was here
      -- 
      I hate storms, but calms undermine my spirits.
       -- Bernard Moitessier, "The Long Way"

        If your variables have several hundred lines wide scopes, you've got a problem. Such a variable is just very very very slightly better than an outright global.

        Keep in mind that Perl has BLOCK scoping, not subroutine scoping. So a variable declared within a block (whether it's a block that belongs to a loop, an if() or just a bare block) only "exists" within that block, not in the whole subroutine. So do declare your variables in the smallest possible block and you will not have to worry about accidentally "destroying" a variable. You can (and at times should) even create blocks just to restrict the scope of a variable!

        Jenda
        Enoch was right!
        Enjoy the last years of Rome.

        I would consider your example a coding problem, a mistake I would expect warnings to catch, not strict. My original comment was just a play on words - my( declare ), kamikaze( specific type of suicide )

        Then again, one could argue some refactoring is long overdue when you have a scope that lasts for, I quote, a couple of hundred lines.

Re: Help! My variables are jumping off a cliff!
by dave_the_m (Monsignor) on Feb 26, 2012 at 08:40 UTC
    Note also that the two declarations introduce two separate variables that are in scope in different parts of the block; i.e. the second declaration isn't a NOOP:
    my $x = 1; sub f1 { $x } my $x = 2; sub f2 { $x } print f1(), f2(), "\n"; # prints "12"

    Dave.

Re: Help! My variables are jumping off a cliff!
by tangent (Parson) on Feb 26, 2012 at 04:22 UTC
    From the docs:
    strict vars
    This generates a compile-time error if you access a variable that wasn't declared via our or use vars, localized via my(), or wasn't fully qualified.
    You're not doing any of those things, you're just not not doing one of them twice.
Re: Help! My variables are jumping off a cliff!
by JavaFan (Canon) on Feb 26, 2012 at 10:09 UTC
    No, it's not. And if you turn warnings on, Perl will point out to you that you may make a mistake. Note that in many cases, it's actually harmless.

    In the early years of Perl5, the for my $var syntax was illegal. If you wanted a lexical variable for your iterator, you'd write:

    my $i; for $i (LIST) { ... }
    It would not be uncommon to have several my $i;'s in the same block.

    But that's harmless.

Re: Help! My variables are jumping off a cliff!
by CountZero (Bishop) on Feb 26, 2012 at 19:08 UTC
    I don't see the problem with adding a simple "use warnings". It is not as if it sends you an invoice every time you use it.

    If it pleases you, your comments on what "use strict" should or shouldn't do are hereby noted and filed.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

    My blog: Imperial Deltronics
Re: Help! My variables are jumping off a cliff!
by Anonymous Monk on Feb 26, 2012 at 07:43 UTC

    See perl5i - Fix as much of Perl 5 as possible in one pragma

    This includes Modern::Perl which makes all warnings fatal, including the one you're complaining strict doesn't catch

      Minor nitpick: Modern::Perl doesn't make warnings fatal. It won't as long as I'm the maintainer.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (1)
As of 2024-04-25 04:10 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found