Modules, global variables and such

Discussion in 'Perl Misc' started by January Weiner, Feb 10, 2008.

  1. Hello,

    I have the following problem. I had a script that contained only one
    global variable which was called $DEBUG. I just used it to print out
    various think or do some checks in debugging mode

    print "number of objects $n_obj\n" if $DEBUG ;
    check_sanity if $DEBUG ;

    The program grew and now I splitted it up into several modules.

    Question: what to do with the debug variable?

    * I could make it local to all of the functions, but I would really hate
    passing it through to each of the functions separately. Firstly, IMO this
    is one of the few cases where global variables are justified, and second,
    this would require me to make hundreds of modifications in the code.

    * I could make it a global variable in each of the modules, and create a
    function that switches on the debugging for one module only. This would
    have the advantage that I could specify which module to debug.
    Disadvantage is that I need to remember to switch it on in every module
    if I want to switch it on globally.

    * Finally, I could make a separate module with generic tests for sanity and
    printing warning messages, and that module would hold the only instance
    of the $DEBUG variable. Again, many modifications in the code required.

    Of course, I can imagine that there are gazillions of other ways of doing
    that, and that there are specific modules that do precisely what I want.
    What route would you recommend?

    Regards,

    January
     
    January Weiner, Feb 10, 2008
    #1
    1. Advertising

  2. January Weiner wrote:
    > I have the following problem. I had a script that contained only one
    > global variable which was called $DEBUG. I just used it to print out
    > various think or do some checks in debugging mode
    >
    > print "number of objects $n_obj\n" if $DEBUG ;
    > check_sanity if $DEBUG ;
    >
    > The program grew and now I splitted it up into several modules.
    >
    > Question: what to do with the debug variable?
    >
    > * I could make it local to all of the functions, but I would really hate
    > passing it through to each of the functions separately. Firstly, IMO this
    > is one of the few cases where global variables are justified, and second,
    > this would require me to make hundreds of modifications in the code.
    >
    > * I could make it a global variable in each of the modules, and create a
    > function that switches on the debugging for one module only. This would
    > have the advantage that I could specify which module to debug.
    > Disadvantage is that I need to remember to switch it on in every module
    > if I want to switch it on globally.
    >
    > * Finally, I could make a separate module with generic tests for sanity and
    > printing warning messages, and that module would hold the only instance
    > of the $DEBUG variable. Again, many modifications in the code required.


    You didn't mention the simplest way:

    Keep it a global variable in one of the modules and use its fully
    qualified name when calling it from other modules, e.g. $MyModule::DEBUG

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
     
    Gunnar Hjalmarsson, Feb 10, 2008
    #2
    1. Advertising

  3. Gunnar Hjalmarsson <> wrote:
    > > * Finally, I could make a separate module with generic tests for sanity and
    > > printing warning messages, and that module would hold the only instance
    > > of the $DEBUG variable. Again, many modifications in the code required.


    > You didn't mention the simplest way:


    > Keep it a global variable in one of the modules and use its fully
    > qualified name when calling it from other modules, e.g. $MyModule::DEBUG


    This is more or less my third way. It requires modifying each of the
    statements containing $DEBUG and including the module in all the other
    modules and the main code. But yes, I am considering this, thanks!

    j.
     
    January Weiner, Feb 10, 2008
    #3
  4. Abigail <> wrote:
    > You seem to have the impression that if you're using a variable
    > $MyModule::DEBUG, you have to have a MyModule.pm, and you have
    > to 'use' that file.


    > That's not true.



    > package Fnurd;


    > use strict;
    > use warnings;


    > say "Hi, I'm a debugging message." if $MyModule::DEBUG;


    Ah, OK. I always used only functions exported from modules or OO modules.
    These must be exported and the modules must be imported. I assumed that the
    same holds for the variables.

    j.
     
    January Weiner, Feb 10, 2008
    #4
  5. Abigail <> wrote:
    > That's what I usually do, except that put the variable in main, so I
    > can just use $::DEBUG.


    This is it! Thank you (both) very much.

    > srand 123456;$-=rand$_--=>@[[$-,$_]=@[[$_,$-]for(reverse+1..(@[=split
    > //=>"IGrACVGQ\x02GJCWVhP\x02PL\x02jNMP"));print+(map{$_^q^"^}@[),"\n"


    'eresal nPhkuHrJ cteatro'? There is something disconcerting in this
    message...

    j.
     
    January Weiner, Feb 10, 2008
    #5
  6. Abigail schrieb:
    >
    > You seem to have the impression that if you're using a variable
    > $MyModule::DEBUG, you have to have a MyModule.pm, and you have
    > to 'use' that file.
    >
    > That's not true.
    >
    >
    > package Fnurd;
    >
    > use strict;
    > use warnings;
    >
    > say "Hi, I'm a debugging message." if $MyModule::DEBUG;
    >
    >
    > works well.
    >
    >
    > Abigail


    For curious lurkers like me, soaking up wisdom from c.l.p.m, I think it
    should be mentioned that $MyModule::DEBUG needs to be declared via 'our'
    for this to work, because:

    $ perl -Mstrict -Mwarnings -le'
    package MyModule;
    my $DEBUG = 1;
    package Fnurd;
    print "Debug on" if $MyModule::DEBUG;
    '
    Name "MyModule::DEBUG" used only once: possible typo at -e line 5.

    whereas with 'our':

    $ perl -Mstrict -Mwarnings -le'
    package MyModule;
    our $DEBUG = 1;
    package Fnurd;
    print "Debug on" if $MyModule::DEBUG;
    '
    Debug on


    But then I don't even have to use the fully qualified name:

    $ perl -Mstrict -Mwarnings -le'
    package MyModule;
    our $DEBUG = 1;
    package Fnurd;
    print "Debug on" if $DEBUG;
    '
    Debug on


    Toying a little more, I find that

    $ perl -Mstrict -Mwarnings -le'
    package MyModule;
    my $DEBUG = 1;
    package Fnurd;
    print "Debug on" if $DEBUG;
    '
    Debug on

    works equally well.

    What am I not understanding?

    Thank you,
    Andreas Pürzer

    --
    Have Fun,
    and if you can't have fun,
    have someone else's fun.
    The Beautiful South
     
    Andreas Pürzer, Feb 10, 2008
    #6
  7. Andreas Pürzer wrote:
    > Abigail schrieb:
    >> January Weiner wrote:
    >>> Gunnar Hjalmarsson <> wrote:
    >>>> Keep it a global variable in one of the modules and use its fully
    >>>> qualified name when calling it from other modules, e.g. $MyModule::DEBUG
    >>>
    >>> This is more or less my third way. It requires modifying each of the
    >>> statements containing $DEBUG and including the module in all the other
    >>> modules and the main code. But yes, I am considering this, thanks!

    >>
    >> You seem to have the impression that if you're using a variable
    >> $MyModule::DEBUG, you have to have a MyModule.pm, and you have
    >> to 'use' that file.
    >>
    >> That's not true.
    >>
    >> package Fnurd;
    >>
    >> use strict;
    >> use warnings;
    >>
    >> say "Hi, I'm a debugging message." if $MyModule::DEBUG;
    >>
    >> works well.

    >
    > For curious lurkers like me, soaking up wisdom from c.l.p.m, I think it
    > should be mentioned that $MyModule::DEBUG needs to be declared via 'our'
    > for this to work, because:
    >
    > $ perl -Mstrict -Mwarnings -le'
    > package MyModule;
    > my $DEBUG = 1;
    > package Fnurd;
    > print "Debug on" if $MyModule::DEBUG;
    > '
    > Name "MyModule::DEBUG" used only once: possible typo at -e line 5.


    That's because the my() declared $DEBUG and $MyModule::DEBUG are two
    different variables...

    > whereas with 'our':
    >
    > $ perl -Mstrict -Mwarnings -le'
    > package MyModule;
    > our $DEBUG = 1;
    > package Fnurd;
    > print "Debug on" if $MyModule::DEBUG;
    > '
    > Debug on
    >
    > But then I don't even have to use the fully qualified name:
    >
    > $ perl -Mstrict -Mwarnings -le'
    > package MyModule;
    > our $DEBUG = 1;
    > package Fnurd;
    > print "Debug on" if $DEBUG;
    > '
    > Debug on


    You do have to use the fully qualified name if you call the variable
    from somewhere outside the MyModule package.

    > Toying a little more, I find that
    >
    > $ perl -Mstrict -Mwarnings -le'
    > package MyModule;
    > my $DEBUG = 1;
    > package Fnurd;
    > print "Debug on" if $DEBUG;
    > '
    > Debug on
    >
    > works equally well.


    Not if you call it from some other module or from the main script.

    > What am I not understanding?


    Maybe you didn't read the whole thread carefully enough? ;-)

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
     
    Gunnar Hjalmarsson, Feb 10, 2008
    #7
  8. January Weiner

    Ben Morrow Guest

    Quoth Gunnar Hjalmarsson <>:
    > Andreas Pürzer wrote:
    >
    > > whereas with 'our':
    > >
    > > $ perl -Mstrict -Mwarnings -le'
    > > package MyModule;
    > > our $DEBUG = 1;
    > > package Fnurd;
    > > print "Debug on" if $MyModule::DEBUG;
    > > '
    > > Debug on
    > >
    > > But then I don't even have to use the fully qualified name:
    > >
    > > $ perl -Mstrict -Mwarnings -le'
    > > package MyModule;
    > > our $DEBUG = 1;
    > > package Fnurd;
    > > print "Debug on" if $DEBUG;
    > > '
    > > Debug on

    >
    > You do have to use the fully qualified name if you call the variable
    > from somewhere outside the MyModule package.


    No, not if you use 'our'. An often-overlooked property of 'our' is that
    it creates a lexical alias to the package variable: in simple terms, you
    can use that variable unqualified for the rest of the lexical scope,
    even if you change package. This is why the second example above works
    as it does.

    > > Toying a little more, I find that
    > >
    > > $ perl -Mstrict -Mwarnings -le'
    > > package MyModule;
    > > my $DEBUG = 1;
    > > package Fnurd;
    > > print "Debug on" if $DEBUG;
    > > '
    > > Debug on
    > >
    > > works equally well.

    >
    > Not if you call it from some other module or from the main script.


    More precisely: if you attempt to use it in some other lexical scope.
    Package statements are irrelevant for lexicals, so if you have some code
    in another file that is in package MyModule it still can't see the
    lexical.

    Ben
     
    Ben Morrow, Feb 10, 2008
    #8
  9. January Weiner

    Ben Morrow Guest

    Quoth :
    > _
    > Gunnar Hjalmarsson () wrote on VCCLXXVI September
    > MCMXCIII in <URL:news:>:
    > -: January Weiner wrote:
    > -: > I have the following problem. I had a script that contained only one
    > -: > global variable which was called $DEBUG. I just used it to print out
    > -: > various think or do some checks in debugging mode

    <snip>
    > -:
    > -: You didn't mention the simplest way:
    > -:
    > -: Keep it a global variable in one of the modules and use its fully
    > -: qualified name when calling it from other modules, e.g. $MyModule::DEBUG
    >
    > That's what I usually do, except that put the variable in main, so I
    > can just use $::DEBUG.


    If this code might be used in some other, unrelated program (that is,
    the debugging state belongs with the module, not the program as a whole)
    you can create a package global and then import it into your other
    packages:

    package MyModule;

    require 'Exporter';
    our @ISA = 'Exporter';
    our @EXPORT_OK = qw/$DEBUG/;

    our $DEBUG;

    __DATA__

    package MyModule::Foo;

    use MyModule qw/$DEBUG/;

    # now just use $DEBUG, as before

    __DATA__

    Ben
     
    Ben Morrow, Feb 10, 2008
    #9
  10. January Weiner wrote:
    > Hello,
    >
    > I have the following problem. I had a script that contained only one
    > global variable which was called $DEBUG. I just used it to print out
    > various think or do some checks in debugging mode
    >
    > print "number of objects $n_obj\n" if $DEBUG ;
    > check_sanity if $DEBUG ;
    >


    This post is orthogonal to the other messages in this thread, but you
    may want to check out

    Carp::Assert
    Log::Log4perl

    Mark
     
    Mark Clements, Feb 10, 2008
    #10
  11. Ben Morrow wrote:
    > Quoth Gunnar Hjalmarsson <>:
    >> Andreas Pürzer wrote:
    >>
    >>> whereas with 'our':
    >>>
    >>> $ perl -Mstrict -Mwarnings -le'
    >>> package MyModule;
    >>> our $DEBUG = 1;
    >>> package Fnurd;
    >>> print "Debug on" if $MyModule::DEBUG;
    >>> '
    >>> Debug on
    >>>
    >>> But then I don't even have to use the fully qualified name:
    >>>
    >>> $ perl -Mstrict -Mwarnings -le'
    >>> package MyModule;
    >>> our $DEBUG = 1;
    >>> package Fnurd;
    >>> print "Debug on" if $DEBUG;
    >>> '
    >>> Debug on

    >> You do have to use the fully qualified name if you call the variable
    >> from somewhere outside the MyModule package.

    >
    > No, not if you use 'our'. An often-overlooked property of 'our' is that
    > it creates a lexical alias to the package variable: in simple terms, you
    > can use that variable unqualified for the rest of the lexical scope,
    > even if you change package.


    Well, yes, but note that this thread was initially about calling the
    $DEBUG variable from other modules, which typically are both different
    packages and different lexical scopes. So Andreas' statement, that the
    fully qualified name isn't necessary, isn't normally applicable to the
    situation that was initially discussed.

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
     
    Gunnar Hjalmarsson, Feb 10, 2008
    #11
  12. Andreas Pürzer <> wrote:
    > Abigail schrieb:
    >>
    >> You seem to have the impression that if you're using a variable
    >> $MyModule::DEBUG, you have to have a MyModule.pm, and you have
    >> to 'use' that file.
    >>
    >> That's not true.
    >>
    >>
    >> package Fnurd;
    >>
    >> use strict;
    >> use warnings;
    >>
    >> say "Hi, I'm a debugging message." if $MyModule::DEBUG;
    >>
    >>
    >> works well.
    >>
    >>
    >> Abigail

    >
    > For curious lurkers like me, soaking up wisdom from c.l.p.m, I think it
    > should be mentioned that $MyModule::DEBUG needs to be declared via 'our'
    > for this to work, because:



    No it doesn't.


    > $ perl -Mstrict -Mwarnings -le'
    > package MyModule;
    > my $DEBUG = 1;



    Change that last line above to:

    $MyModule::DEBUG = 1;

    and it will work fine.

    For package variables, strict vars requires EITHER a declaration (if
    you want to use the short version of the name (ie. unqualified))
    OR a fully-qualified name.

    Note that your version uses a "lexical variable". My mod uses
    a "package variable".


    > package Fnurd;
    > print "Debug on" if $MyModule::DEBUG;
    > '
    > Name "MyModule::DEBUG" used only once: possible typo at -e line 5.
    >
    > whereas with 'our':
    >
    > $ perl -Mstrict -Mwarnings -le'
    > package MyModule;
    > our $DEBUG = 1;
    > package Fnurd;
    > print "Debug on" if $MyModule::DEBUG;
    > '
    > Debug on



    Now your code is using a package variable too.


    > But then I don't even have to use the fully qualified name:
    >
    > $ perl -Mstrict -Mwarnings -le'
    > package MyModule;
    > our $DEBUG = 1;
    > package Fnurd;
    > print "Debug on" if $DEBUG;
    > '
    > Debug on



    That is because our() is lexically scoped (like it says in perldoc -f our).

    In your program above, the our() is scoped to the entire file, so
    it is in effect down in the Fnurd package.


    > Toying a little more, I find that
    >
    > $ perl -Mstrict -Mwarnings -le'
    > package MyModule;
    > my $DEBUG = 1;
    > package Fnurd;
    > print "Debug on" if $DEBUG;
    > '
    > Debug on
    >
    > works equally well.



    It would not work if the two packages were in different files,
    because lexical variables can NEVER cross file boundaries.


    > What am I not understanding?



    Most of it seems to the the difference between lexical variables (my)
    and package variables (our or fully-qualified). See

    perldoc -q "dynamic and lexical"

    and

    "Coping with Scoping":

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



    --
    Tad McClellan
    email: perl -le "print scalar reverse qq/moc.noitatibaher\100cmdat/"
     
    Tad J McClellan, Feb 11, 2008
    #12
  13. Tad J McClellan schrieb:

    > Andreas Pürzer <> wrote:
    >
    >>I think it
    >>should be mentioned that $MyModule::DEBUG needs to be declared via 'our'
    >>for this to work, because:

    >
    >
    >
    > No it doesn't.
    >
    > For package variables, strict vars requires EITHER a declaration (if
    > you want to use the short version of the name (ie. unqualified))
    > OR a fully-qualified name.
    >
    > Note that your version uses a "lexical variable". My mod uses
    > a "package variable".
    >
    >
    >


    [snip]

    > It would not work if the two packages were in different files,
    > because lexical variables can NEVER cross file boundaries.
    >
    >
    >
    >>What am I not understanding?

    >
    >
    >
    > Most of it seems to the the difference between lexical variables (my)
    > and package variables (our or fully-qualified). See
    >
    > perldoc -q "dynamic and lexical"
    >
    > and
    >
    > "Coping with Scoping":
    >
    > http://perl.plover.com/FAQs/Namespaces.html
    >
    >
    >


    I've already read those, but it seems it's time to read them again...
    And like Gunnar suggested, I will try to read them much more carefully
    this time ;->

    Thanks to all who responded,
    Andreas Pürzer

    --
    Have Fun,
    and if you can't have fun,
    have someone else's fun.
    The Beautiful South
     
    Andreas Pürzer, Feb 11, 2008
    #13
  14. Gunnar Hjalmarsson schrieb:

    > Ben Morrow wrote:
    >
    >> Quoth Gunnar Hjalmarsson <>:
    >>
    >>> Andreas Pürzer wrote:
    >>>
    >>>>
    >>>> But then I don't even have to use the fully qualified name:
    >>>>
    >>>
    >>> You do have to use the fully qualified name if you call the variable
    >>> from somewhere outside the MyModule package.

    >>
    >>
    >> No, not if you use 'our'. An often-overlooked property of 'our' is that
    >> it creates a lexical alias to the package variable: in simple terms, you
    >> can use that variable unqualified for the rest of the lexical scope,
    >> even if you change package.

    >
    >
    > Well, yes, but note that this thread was initially about calling the
    > $DEBUG variable from other modules, which typically are both different
    > packages and different lexical scopes. So Andreas' statement, that the
    > fully qualified name isn't necessary, isn't normally applicable to the
    > situation that was initially discussed.
    >


    Oops, an Usenet-Thread gone sideways with me to blame, sorry about that ;->
    SCNR

    Thanks to both of you,
    Andreas Pürzer

    --
    Have Fun,
    and if you can't have fun,
    have someone else's fun.
    The Beautiful South
     
    Andreas Pürzer, Feb 11, 2008
    #14
  15. Andreas Pürzer wrote:
    > Gunnar Hjalmarsson schrieb:
    >> Ben Morrow wrote:
    >>> Quoth Gunnar Hjalmarsson <>:
    >>>> You do have to use the fully qualified name if you call the variable
    >>>> from somewhere outside the MyModule package.
    >>>
    >>> No, not if you use 'our'. An often-overlooked property of 'our' is that
    >>> it creates a lexical alias to the package variable: in simple terms, you
    >>> can use that variable unqualified for the rest of the lexical scope,
    >>> even if you change package.

    >>
    >> Well, yes, but note that this thread was initially about calling the
    >> $DEBUG variable from other modules, which typically are both different
    >> packages and different lexical scopes. So Andreas' statement, that the
    >> fully qualified name isn't necessary, isn't normally applicable to the
    >> situation that was initially discussed.

    >
    > Oops, an Usenet-Thread gone sideways with me to blame, sorry about that ;->
    > SCNR


    That's absolutely not a problem; as a matter of fact it happens all the
    time, and it makes Usenet discussions more interesting. :)

    My point was rather about context. Your code examples were posted in a
    context, and you'd better be aware of the context when discussing them.

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
     
    Gunnar Hjalmarsson, Feb 11, 2008
    #15
  16. Gunnar Hjalmarsson schrieb:
    > Andreas Pürzer wrote:
    >
    >> Oops, an Usenet-Thread gone sideways with me to blame, sorry about
    >> that ;->
    >> SCNR

    >
    >
    > That's absolutely not a problem; as a matter of fact it happens all the
    > time, and it makes Usenet discussions more interesting. :)
    >


    hence the SCNR, maybe I should have used <irony/> :)

    > My point was rather about context. Your code examples were posted in a
    > context, and you'd better be aware of the context when discussing them.
    >


    Point taken. But if I hadn't misinterpreted context, I hadn't learnt
    from this discussion. Maybe this is what perldiag calls 'Unbalanced
    context'? :)

    Thank you,
    Andreas Pürzer

    --
    Have Fun,
    and if you can't have fun,
    have someone else's fun.
    The Beautiful South
     
    Andreas Pürzer, Feb 11, 2008
    #16
  17. Thanks for all the answers, I learned a lot. I now use $::DEBUG for my
    purposes.

    Cheers,
    j.
     
    January Weiner, Mar 2, 2008
    #17
    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. Fuming Wang
    Replies:
    7
    Views:
    341
    =?iso-8859-1?q?Fran=E7ois_Pinard?=
    Jul 17, 2003
  2. KN
    Replies:
    1
    Views:
    275
    Jerry Sievers
    Apr 17, 2004
  3. Aaron Deskins

    Global variables in modules/functions

    Aaron Deskins, Nov 19, 2004, in forum: Python
    Replies:
    7
    Views:
    4,274
    Aaron Deskins
    Nov 22, 2004
  4. Replies:
    6
    Views:
    341
    John Machin
    Dec 24, 2004
  5. Bart
    Replies:
    4
    Views:
    488
    Bart van Deenen
    Feb 23, 2005
Loading...

Share This Page