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?

Replies are listed 'Best First'.
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

      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

    A reply falls below the community's threshold of quality. You may see it by logging in.
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 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 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.

    A reply falls below the community's threshold of quality. You may see it by logging in.
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".

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