Beefy Boxes and Bandwidth Generously Provided by pair Networks RobOMonk
Perl: the Markov chain saw
 
PerlMonks  

Clearing user defined variables

by Wassercrats
on Apr 13, 2004 at 06:57 UTC ( #344639=perlquestion: print w/ replies, xml ) Need Help??
Wassercrats has asked for the wisdom of the Perl Monks concerning the following question:

Am I the only one who thinks it's dumb for there to be no built-in way to clear only user defined variables, to avoid the problem with the reset function clearing stuff like @INC? I have a 3200 line script that I wrote using global variables, but I decided to turn it into a server type thing that runs continuously, waiting for someone to give it a command. Unfortunately, now I must clear extra variables and I'm not sure which ones so I want to clear them all. Reloading the script would be less efficient and it would require an extra file so I could bypass the administrator authentication routine that I want to be executed only once. I came up with:
open(IN, $0); @file = <IN>; close IN; $FILE = join (' ',@file); while ($FILE =~ s/[\@\$][a-zA-Z]\w+//) { $ONE_VAR = $&; $ALL_VAR .= $ONE_VAR =~ /\$/ ? "$ONE_VAR='';" : "$ONE_VAR=();"; } eval $ALL_VAR;
So now I could add lines to ignore whatever variables I want to not be cleared. Is there a better way? Would this be suitable for the Snippets section?

Comment on Clearing user defined variables
Download Code
Re: Clearing user defined variables
by tachyon (Chancellor) on Apr 13, 2004 at 07:18 UTC

    Is there a better way?

    Yes it is called scoping your variables and avoiding/limiting the use of global vars. I am amazed you can get 3200 lines to work (presumably one long file) in a stable fashion using globals.

    If you wanted to modify your program towards less globals one approach is to use a %globals hash that contains all your globals. When you want to 'reset' the sutem you just reset %globals.

    cheers

    tachyon

      I don't like the limitations of scoping my variables. Aren't there pleantly of lower level language that don't even offer that feature? That never bothered me. It seems like it would just slow me down. It's too late for that now anyway.
        Aren't there pleantly of lower level language that don't even offer that feature? Well, there's assembler, and ... uf - that's pretty much it, unless you count stack oriented languages like forth and postscript where the concept doesn't even exist.

        And we program in Perl, because it is better than those low-level languages. One of the ways it is better is scoped variables.

        If you think non-scoped variables don't bother you, try this experiment: rewrite your 3200 line script to use scoped variables (if you're such a hot coder the non-scoped variables never bothered you, this should be peanuts to you). Then maintain both versions for a month, adding the same features to each version. I'm betting you will find maintaining the scoped version much easier.

      He can't "just reset %globals@": the reset takes an argument that is the first letter (or range of first letters) of variable name.

      So if he put in reset 'g', it would reset all variables starting with g, including $g, @great, %google, and if he reset 'globals', it would reset all variables starting with a,b,g,l,o or s.

      IMHO, reset is bad karma.

        Unless I'm missing something, all reset does is undef a gang of variables at once. All that the OPs snippet does is assigns the nothing string to scalars, and the empty set to arrays, so I guess it'd be
        foreach(keys %globals){ if( ref $globals{$_} eq 'ARRAY' ){ @{ $globals{$_} } = (); } else { $globals{$_} = ''; } }

        MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
        I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
        ** The third rule of perl club is a statement of fact: pod is sexy.

        Sorry I was a little unclear. By 'reset' I meant

        %globals = (); # or _init(\%globals);
        or similar not using reset itself. This sort of 'reset' code is found in modules like CGI.pm to reset the globals and is used as a cleanup handler in mod_perl.

        cheers

        tachyon

Re: Clearing user defined variables
by matija (Priest) on Apr 13, 2004 at 07:25 UTC
    I had to check if the reset function really exists at all, and was shocked to find that it does.

    Yes, I think it's safe to say you should use another way to do what you want.

    My advice would be to use my lexically local variables - declare them at the start of your loop, and initialize them the way you want them.

    The method you are proposing is dangereous, inefficient, and pretty much guaranteed to break the moment you make a change to your script without paying specific attention to your hack.

      Strange... I had to check reset too. I knew that it resets ?? patterns but I thought it doesn't do anything else (maybe something with .. flip-flops?). But after all this talk in the thread about it I started to suspect that it does something else too. And indeed. (This is not a new feature, it was in 5.005_03 too)

Re: Clearing user defined variables
by PodMaster (Abbot) on Apr 13, 2004 at 07:45 UTC
    Am I the only one who thinks it's dumb for there to be no built-in way to clear only user defined variables, to avoid the problem with the reset function clearing stuff like @INC?
    I don't think it's dumb, and I'm pretty sure there is a "built-in" way to do it.
    Is there a better way?
    If I were you I'd rewrite the script. In the very least just stick it in a __PACKAGE__ other than main, that way when you reset, @INC and family won't be affected.
    Would this be suitable for the Snippets section?
    I'd say it qualifies as a snippet. A better solution would be to use B::Xref.

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.

Re: Clearing user defined variables
by gmpassos (Priest) on Apr 13, 2004 at 08:08 UTC
    Well, reset() implementation really suxs, but Perl always let you to implement everything that you want. So, this 2 functions can help you:

    Note that I encourage you to take a look in object orientation! Forget this ugly and stupid structured codes, this doesn't work very well. After learn OO you will see that with it you will be able to reuse better your codes, maintan, and you will be possible to make solutions for things much more complex, since you won't waste time with issues that structured codes create, and a bunch of functions that aren't made to work together or in other codes.

    Graciliano M. P.
    "Creativity is the expression of the liberty".

Re: Clearing user defined variables
by simon.proctor (Vicar) on Apr 13, 2004 at 08:46 UTC
    Aside from agreeing with Tachyon that if you must have a stack of globals then a hash is the way to go, I was wondering if you had used sub routines or not?

    Accessing and modifying globals from within a subroutine rather than passing in parameters is (IMHO) a bad thing.

    Additionally, have you looked at the number of variables you have with respect to them being configuration options or constants? If you find a stack of those then it may help with your clean up as you wouldn't need to clear those and can use the constant pragma or have a configuration file instead.

    From your post, I am assuming that you have to clean up once the application has finished servicing a command. Returning to its wait state ready for another command at some point in the future. Perhaps you should look specifically at this area and consider your service code as something you can put into a module. Perhaps one module per command. You can then handle cleanup of each command specifically within each module yet have a smaller global cleanup in your main servicing loop.

    You may find this easier to maintain - this is an approach I have used before and its saved me many headaches. Its a bit like a strategy pattern implementation (but how far is down to you).
Re: Clearing user defined variables
by castaway (Parson) on Apr 13, 2004 at 08:48 UTC
    I may be missing something here, but why go to all this trouble? Whats wrong with just writing a subroutine which sets all the variables to whatever default value you want them to have, and calling that whenever appropriate?

    Eg:

    sub reset_all { $x = undef; $counter = 1; }
    And so on..

    C.

      Such a subroutine would be longer than my hack because of the number of variables. I'd need to use my hack (or B::Xref) to determine all the variables anyway. I don't have all my variables memorized, and I'm not sure which ones need to be reset for my new implementation so it's not so easy to implement some of the suggestions I've gotten. I didn't anticipate using the script in such a way, or else I would have cleared all the variables in the proper places as I created them.

      There are a few ways to deal with this, and it's no big deal in my case, but something needs to be done about reset.

      ...still have to look into PodMasters __PACKAGE__ idea.

      I have 14 subroutines.
        If you dont know which ones, then find out? Else all you have is a mess, if you cant keep track of which variables you're using where. Of course it would be long, its just an alternative to the scoped variables you probably should be using. Globals arent so bad if you know exactly whats being used where and how, and make a note/comment about it somewhere. If you dont, well, throw the thing in the bitbuecket and start again :)

        C.

Re: Clearing user defined variables
by Wassercrats on Apr 13, 2004 at 22:23 UTC

    PodMaster's package suggestion works great. I just wish it was suggested to the other people around the internet who had the same problem and were only told about reset and its limitations. There should be a reference to package in the reset doc.

    But I'm wondering, say I want to use my technique to list all the variables, maybe in addition to the hash trick that eliminates duplicates. The file I'm parsing is the current, already loaded file. Is there a faster/better way to get the current file into a variable than to reopen it?

Re: Clearing user defined variables
by Wassercrats on Apr 14, 2004 at 07:52 UTC
    The package idea was good while it lasted, but I decided to use my method (though I'll adjust the regex to delete the already searched part of the code) because according to Programming Perl, "Use of reset is vaguely deprecated." If it won't be in Perl 6, I'm not using it.
Re: Clearing user defined variables
by Wassercrats on Apr 15, 2004 at 03:52 UTC

    The latest version of my reset emulator, with an option to print variables and their values is here.

    Sorry, I don't remember the special ID linking rules here, and there's no reminder in site.

      It goes like this: [id://345239]
      (yep, counterintuitive and hard to remember).
      Did you not even think to check the PerlMonks FAQ?

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (9)
As of 2014-04-17 08:07 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (441 votes), past polls