http://qs321.pair.com?node_id=100835

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

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

Replies are listed 'Best First'.
Re: Need some help with a dodgy variable
by arturo (Vicar) on Jul 30, 2001 at 15:57 UTC

    You're probably declaring the variable with my within the sub, which means that the value you define is invisible outside that subroutine unless you do something to make it visible to code outside the subroutine. You have two straightforward options:

    1. Declare the variable outside of any block (you can use my for this or make it a global; it will be modifiable by the subroutine.
    2. have the subroutine return the value.

    For stylistic reasons, I prefer the second, as it lets anyone else reading your code immediately know where to look to find out where the value's getting set. Sometimes this isn't appropriate, though. Here are examples:

    # strategy 1 my $var; # other stuff sub mysub { # do stuff -- don't declare my $var here, though. It will mask th +e one you want to set. $var = "whatever"; # sets $var declared above to "whatever" }
    # option 2 my $var = mysub(); sub mysub { # do stuff $var = "whatever"; return $var; # return is optional here, but makes what's going on + explicit. }

    HTH

    perl -e 'print "How sweet does a rose smell? "; chomp ($n = <STDIN>); +$rose = "smells sweet to degree $n"; *other_name = *rose; print "$oth +er_name\n"'
Re: Need some help with a dodgy variable
by davorg (Chancellor) on Jul 30, 2001 at 15:52 UTC

    Difficult to know without seeing the code, but I'd guess that you either need to declare it as a package variable (with use vars or our) or a lexical variable at the file level (using my).

    Or you could pass it as a parameter to the fumctions where it is needed.

    --
    <http://www.dave.org.uk>

    Perl Training in the UK <http://www.iterative-software.com>

Re: Need some help with a dodgy variable
by tachyon (Chancellor) on Jul 30, 2001 at 18:09 UTC
      It would be pointless me posting my code as my question explains it exactly how it is.
      Ive only been using perl for the last two weeks, so bear with me please.

      I tried using 'use strict' but that makes my program to not work at all. Its definately not a my variable.

      heres an example then of what i mean:

      sub this_sub { $this_variable = "Jeff"; } sub that_sub { print "Hello "."$this_variable"; }

      Imagine these subs have been called accordingly, and when the last one is called, it just says "Hello ".
        A couple of remarks here.
        • If 'use strict' makes your program break, then take the time to fix what strict is complaining about. It will never complain about something that it shouldn't. (At least, not at the level you say you're programming at.)
        • Now that you have posted even just an example piece of code, we now know exactly what it is you're having a problem with. There are a number of potential problems you might have been having. Now that you have an example, I can give you a suggestion.
        Try the following code. Run it "as is" once, to understand what it's doing. (You might have to change where the Perl interpreter is.)

        #!/usr/local/bin/perl use strict; use warnings; my $file_scoped_variable = ''; sub modify_var { $file_scoped_variable = "Var Set"; } sub print_var { print "Hello ... " , $file_scoped_variable , "\n"; } &modify_var; &print_var; __END__
        If, when you try that small script, it doesn't work, then tell us why it doesn't work. Don't just say "Sorry, it's broken."

        The only way to get the result you note is to call that_sub() before this_sub(). This prints "Hello Jeff" just fine

        sub this_sub { $this_variable = "Jeff"; } sub that_sub { print "Hello "."$this_variable"; } this_sub(); that_sub(); # prints Hello Jeff

        All I can presume is that your test case above is not the same as your real code as the test works exactly as expected. this_sub sets the global var $this_variable which is then available everwhere.

        cheers

        tachyon

        s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

(ichimunki) Re: Need some help with a dodgy variable
by ichimunki (Priest) on Jul 30, 2001 at 23:30 UTC
    If you are using multiple files in your script and you assume that "use strict" from the main script will automatically affect all the other scripts, you will run afoul of this scoping issue. The scripts below will exhibit different behavior with respect to globals when strict and my are used than when strict and my are not used. If we really want to use $z in our main scope as a global, we should either pass a reference to it in our sub call (and modify it in place), or set its value based on the return value of our sub call. Or we could not use strict, but we should use strict and figure out a better way to handle our data than indiscriminate use of globals.
    #!/usr/bin/perl -w #this is scope1.pl use strict; #comment out require 'scope2.pl'; my $z = 0; #comment out, we could also leave this # undef, but that generates a bunch of warnings for my $x (1..5) { my $y = multiply( $x ); print "$x * 3 : $y : $z\n"; } _______________________________________ #this is scope2.pl sub multiply { $this = shift; $z = $this * 3; } 1;
Re: Need some help with a dodgy variable
by perchance (Monk) on Jul 30, 2001 at 18:09 UTC
    If I understand correctly, you can make the variable global by adding :: after the $,@, or whatever. If you do so you will not be able to scope it using my, so you can initialze it at your leisure. For example:
    #!/usr/bin/perl -w use strict; $::var = 0; print "Variable is [$::var]\n"; changeVar(); print "Variable is now [$::var]\n"; sub changeVar { $::var = 2; }

    Hope this helps,
    --- perchance
      (Please do not take the following node as a personal insult. It was not meant as such.)

      I must interject that this, while perfectly legal, is horrible programming practice. I've been working on ripping out globals written in exactly this fashion for the past 3 weeks on a side project I wasn't even hired to do.

      Do NOT use ::

      • for variable names unless there simply is not other way
      • to import variables from another package
      • to move variables around within a package
      • to initialize variables for use in another package
      Most especially, NEVER USE THEM TO GET AROUND STRICT. Ever. Never Ever. Not even once, as a joke.

      In fact, please forget that :: exists for variable names. It'll make your life so much easier in the long run, and the people who come after you who have to maintain your code will shower many blessings (instead of curses) upon your head.

        Interesting suggestion. What's wrong with this usage (which I find myself using frequently)? :
        use strict; package MyClass; @MyClass::ISA = 'Whatever';
        Care to explain why?
        For quite a long time (before we started Object-Orienting the project) we used global (::) variables to hold our internal database. Though I can understand why under certain circumstances it might not be wise, to that end we found it appropriate.(And there were mounds of vars there).
        In fact, I have often found myself looking around in other people's code, trying to figure out which of the hundreds of hashes, arrays and scalar defined at the beginning of the script (outside the scope) they were referring to, and where they were changed. At least when they were ::'ed I knew I had to go chase them...
        I appreciate the problems this can cause across packages, but sometimes your scripts standalone.

        If I am missing something - please tell me,
        --- perchance