How do I use global variables safely?

Discussion in 'Perl Misc' started by Graham, Aug 13, 2005.

  1. Graham

    Graham Guest

    I want to be able to allow a variable to be set in one subroutine, and use
    its value in another subroutine, but I obviously can't do this if I use the
    'my' or 'local' functions on the variable in each subroutine. You might say
    just dispense with 'my' or 'local' and let the variable be global. Well I
    was doing that and had no problem until I used ActiveState's 'Perl App' to
    create a standalone executable. This doesn't seem to like global variables
    and is virtually telling me I must 'use strict', and I would if I could, but
    I don't know how to transfer a vairiable's value (I never did fully
    understand lexical scope) Any ideas anyone?
     
    Graham, Aug 13, 2005
    #1
    1. Advertising

  2. Graham

    Klaus Guest

    "Graham" <> wrote in message news:42fddbea.0@entanet...
    > I want to be able to allow a variable to be set in one subroutine, and use
    > its value in another subroutine, but I obviously can't do this if I use

    the
    > 'my' or 'local' functions on the variable in each subroutine.


    correct.

    > You might say
    > just dispense with 'my' or 'local' and let the variable be global.


    That's one solution

    > Well I
    > was doing that and had no problem until I used ActiveState's 'Perl App' to
    > create a standalone executable. This doesn't seem to like global variables
    > and is virtually telling me I must 'use strict',


    I strongly support 'use strict' in any Perl program wich is longer than 2
    lines of code.

    > and I would if I could, but
    > I don't know how to transfer a vairiable's value (I never did fully
    > understand lexical scope) Any ideas anyone?


    Idea 1:
    Alwayse use strict and warnings: just let the variable be global (i.e. a
    package-variable) and use the correct package (that would be "$::") to acces
    the variable.
    ==============================
    use strict;
    use warnings;
    set_glob();
    use_glob();
    sub set_glob { $::glob = "xxx" }
    sub use_glob { print "glob is '$::glob'\n"; }
    ==============================

    Idea 2:
    Alwayse use strict and warnings: just let the variable be global (i.e. a
    package-variable) and employ "our" to make the very same global variable
    accessible in each function.
    ==============================
    use strict;
    use warnings;
    set_glob();
    use_glob();
    sub set_glob { our $glob = "xxx" }
    sub use_glob { our $glob; print "glob is '$glob'\n" }
    ==============================

    Idea 3:
    Alwayse use strict and warnings: just let the variable be a lexical scope
    variable (i.e. introduced by "my") outside the definition of both functions.
    This lexical scope variable is then automatically accessible in each
    function.
    ==============================
    use strict;
    use warnings;
    my $glob;
    set_glob();
    use_glob();
    sub set_glob { $glob = "xxx" }
    sub use_glob { print "glob is '$glob'\n" }
    ==============================

    --
    Klaus
     
    Klaus, Aug 13, 2005
    #2
    1. Advertising

  3. Graham

    Matt Garrish Guest

    "Klaus" <> wrote in message
    news:42fde3d3$0$27362$...
    > "Graham" <> wrote in message news:42fddbea.0@entanet...
    >> I want to be able to allow a variable to be set in one subroutine, and
    >> use
    >> its value in another subroutine, but I obviously can't do this if I use

    >
    > Idea 3:
    > Alwayse use strict and warnings: just let the variable be a lexical scope
    > variable (i.e. introduced by "my") outside the definition of both
    > functions.
    > This lexical scope variable is then automatically accessible in each
    > function.
    > ==============================
    > use strict;
    > use warnings;
    > my $glob;
    > set_glob();
    > use_glob();
    > sub set_glob { $glob = "xxx" }
    > sub use_glob { print "glob is '$glob'\n" }
    > ==============================
    >


    I personally hate using globals like that. It gives you no indication of
    where the value is being set or used (except in simple examples like this),
    which inevitably means sifting through lines and lines of code if something
    goes wrong. My preference would be to go with the obvious:

    my $glob = set_glob();
    use_glob($glob);

    sub set_glob { return 'xxx'; }
    sub use_glob { my $temp_glob = shift; print "glob is $temp_glob\n"; }

    Matt
     
    Matt Garrish, Aug 13, 2005
    #3
  4. Klaus wrote:
    > "Graham" wrote:
    >> I want to be able to allow a variable to be set in one subroutine, and use
    >> its value in another subroutine,


    <snip>

    >> I don't know how to transfer a vairiable's value (I never did fully
    >> understand lexical scope)

    >
    > Idea 1:


    <three ways to use global variables snipped>

    Better yet, idea 4:
    Learn how to pass values between subroutines.
    ==============================
    use strict;
    use warnings;
    my $var = set_var();
    use_var($var);
    sub set_var {
    my $var = 'xxx';
    return $var;
    }
    sub use_var {
    my $var = shift;
    print "var is '$var'\n";
    }
    ==============================

    See "perldoc perlsub".

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
     
    Gunnar Hjalmarsson, Aug 13, 2005
    #4
  5. Graham

    Damian James Guest

    On Sat, 13 Aug 2005 12:34:34 +0100, Graham said:
    > I want to be able to allow a variable to be set in one subroutine, and use
    > its value in another subroutine, but I obviously can't do this if I use the
    > 'my' or 'local' functions on the variable in each subroutine. You might say
    > just dispense with 'my' or 'local' and let the variable be global. Well I
    > was doing that and had no problem until I used ActiveState's 'Perl App' to
    > create a standalone executable. This doesn't seem to like global variables
    > and is virtually telling me I must 'use strict', and I would if I could, but
    > I don't know how to transfer a vairiable's value (I never did fully
    > understand lexical scope) Any ideas anyone?


    You can just declare the variable in a scope that both subs can see:
    #!perl
    use strict;
    use warnings;
    my $var;
    sub foo { $var = $_[0]; }
    sub bar { print "$var\n"; }
    foo('test');
    bar();

    Though other posters have suggested methods involving passing the value
    of a variable into and out of functions, and I'd recommend following their
    advice.

    --Damian
     
    Damian James, Aug 14, 2005
    #5
  6. Graham

    Graham Guest

    > You can just declare the variable in a scope that both subs can see:
    > --Damian

    Silly me!. Yes, as Damian says, if I declare those variables which will be
    used in more than one subroutine at the top of the file, before any
    subroutines are invoked, everything is honky dory. Also, I don't think
    PerlApp was forcing me to 'use strict' after all - that was another problem
    which I've now overcome.

    --Graham
     
    Graham, Aug 14, 2005
    #6
  7. Graham

    Damian James Guest

    On Sun, 14 Aug 2005 14:12:19 +0100, Graham said:
    > PerlApp was forcing me to 'use strict' after all - that was another problem
    > which I've now overcome.


    All the same, I'd strongly suggest using strict anyway, and warnings.
    It will save you time and effort in the long run.

    --Damian
     
    Damian James, Aug 14, 2005
    #7
  8. Graham

    Dave Weaver Guest

    On Sat, 13 Aug 2005 23:00:03 GMT, Damian James <> wrote:
    >
    > You can just declare the variable in a scope that both subs can see:
    > #!perl
    > use strict;
    > use warnings;
    > my $var;
    > sub foo { $var = $_[0]; }
    > sub bar { print "$var\n"; }
    > foo('test');
    > bar();
    >


    You can refine this idea further, so that the access to the variable is
    restricted to certain subs only;

    #!/usr/bin/perl
    use strict;
    use warnings;

    {
    # Definition of $colour restricted
    # to the enclosing block;
    my $colour;

    # This sub can see $colour
    sub set_colour {
    $colour = shift;
    }

    # So can this
    sub get_colour {
    return $colour;
    }
    }
    # No access to $colour below here

    sub something_else {
    ...
    }
     
    Dave Weaver, Aug 15, 2005
    #8
  9. Graham

    Damian James Guest

    On 15 Aug 2005 07:05:10 GMT, Dave Weaver said:
    > ...
    > You can refine this idea further, so that the access to the variable is
    > restricted to certain subs only;

    [Example with scope restricted to surrounding block]

    There's MJD's article on scoping, which is a pretty thorough examination:

    http://perl.plover.com/FAQs/Namespaces.html

    Then there are closures:

    #!/usr/bin/perl
    use warnings;
    use strict;

    $|=1;
    my $t = twirly();
    select(undef,undef,undef,1/8),
    print $t->() for 0..50;

    sub twirly {
    my $i = 0;
    my @char = @_? @_ : qw{/ - \ |};
    sub { "\b"x($i>0).@char[ $i++ % @char ] }
    }

    __END__

    --Damian
     
    Damian James, Aug 15, 2005
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Wayne
    Replies:
    2
    Views:
    501
    Wayne
    Nov 11, 2003
  2. iwinux

    How to use scanf() safely?

    iwinux, Jul 14, 2006, in forum: C Programming
    Replies:
    14
    Views:
    813
  3. Billy Bong

    Use gets Safely

    Billy Bong, Jan 15, 2008, in forum: C Programming
    Replies:
    18
    Views:
    527
    Army1987
    Jan 19, 2008
  4. Bruno Desthuilliers

    eval() == evil? --- How to use it safely?

    Bruno Desthuilliers, Aug 28, 2008, in forum: Python
    Replies:
    17
    Views:
    552
    rustom
    Sep 3, 2008
  5. W. Martin Borgert

    Use eval() safely?

    W. Martin Borgert, Feb 21, 2010, in forum: Python
    Replies:
    6
    Views:
    371
    Gregory Ewing
    Feb 25, 2010
Loading...

Share This Page