in reply to Resetting variables

Lexical scoping exists to make your life easier. You don't need to reset variables if you use lexical scoping to your advantage. Here's a very concise example:

use strict; use warnings; my $i = 0; while( $i++ < 10 ) { no warnings qw/uninitialized/; my $scoped; print "\$scoped contains $scoped\n"; $scoped = 100; }

This snippet uses strict and warnings, but for the purposes of this particular demonstration turns off the "uninitialized value" warning. Next, it loops ten times. Each time, it creates a lexically scoped (my) variable called $scope. It prints that variable's contents (which are essentially empty, or undefined). It then assigns the number 100 to $scoped, and loops. If you weren't using lexical scoping, on the second loop iteration, $scoped would still contain 100, and that would print. But as you see if you run this, on each iteration $scoped is still empty. Why? Because at the end of each while block iteration, the lexical variable named $scoped "falls out of scope" (it disappears, forever gone). And on the next iteration, a new one is created (via 'my').

What you need to do is write your script in such a way that when the player decides to play again, all the variables that need to be reset simply fall out of scope. The ones whos values should be kept would need to have been defined at a broader scope.

This sort of thing is described in perlintro, perlsub and perlsyn, for starters. Therein you'll also read about properly passing parameters to subroutines rather than absorbing values through global osmosis. Welcome to a new way of thinking.


Dave

Replies are listed 'Best First'.
Re^2: Resetting variables
by yacoubean (Scribe) on Dec 21, 2004 at 17:49 UTC
    I'll reply to all of you that told me to use strict and warnings. I am doing that, and my code runs without errors or warnings the first pass. I also have lots of lexical scoping throughout my code, but I couldn't think of a better way to keep the variables I needed so I could use them in all the various subs and such. I tried passing paramaters and other things like that, but I kept getting 'unitialized' errors, so I went back to the global way. I have read perlintro about 50 times, and lots and lots of other documentation, but I'm still learning and making a lot of dumb mistakes. BTW, this game is not finished, and I haven't added in most of the data that I want the game to keep track of between runs (ex. a word list and related logic).

    Obviously this is a case of not enough code, so here is my entire script:

      The particular bug that's causing the error message you're referring to is in the reset_game() sub.

      The problem is that you're assigning a single scalar value '0' to a list. That means that $all_occurrences becomes undefined. Use an undefined value within a character class in a regexp and you get an error message. Try the followng:

      perl -e "my $var; 'string'=~/[$var]/"

      And here's the error...

      Unmatched [ in regex; marked by <-- HERE in m/[ <-- HERE ]/ at -e line + 1.

      If you're getting warnings when running under warnings and strictures, the goal is to understand why. The warnings are telling you something. In this case, you mentioned getting uninitialized value warnings. Instead of fixing the problem, you subverted the warnings, and that allowed bugs to creep in. If you had dug into why you were getting those undefined value warnings, you would have tracked the problem down to your reset sub.


      Dave

        Oops! I pasted an older version of my code...at one point I had that sub coded like this, but went to this incorrect way (as I now understand) to try to fix bugs.
        sub reset_game { ($good_guesses, $bad_guesses) = ""; $tot_found = 0; $found_one = 0; $occurrences = 0; $all_occurrences = 0; $guessed_word = 0; }