in reply to 'my' buggy...

There may well be a bug there, but it might also be a result of this:
  my ($cat) = @_ if @_;
If @_ is empty, $cat will have the value it had the last time you were in the block. This is due to the way perl reuses scratchpads on block entry. Every sub (not every block, mind, but every sub) has a scratchpad associated with it, with space for all the my'd variables reserved in it. If, at runtime, you enter that sub and the default scratchpad isn't in use (because of recursive calls, for example) perl will use the default scratchpad. This saves on time, as the assumption is you won't be recursive and you will enter a sub more than once over the run of the program. Reusing the scratchpad means no time spent to allocate memory each time through.

The interesting bit is that initialization--giving the variables in the scratchpads values--is a runtime thing. Perl doesn't give a default to variables that have values assigned as part of the my, as that'd be a waste of time as well. (Why assign a default that's going to be immediately overwritten?) But your assignment is conditional, and in some cases it won't happen. That means that in those cases where the condition on the initial assignment isn't met no assignment happens at all. And, since perl's reusing scratchpads, you'll just get whatever was in there from the last time around.

Needless to say, this is often not what you want.

Replies are listed 'Best First'.
Re: Re: 'my' buggy...
by japhy (Canon) on Apr 30, 2002 at 16:19 UTC
    Not true (try it). The weirdness only exists when the condition is false at compile-time -- e.g., when a constant like 0 is used.

    _____________________________________________________
    Jeff[japhy]Pinyan: Perl, regex, and perl hacker, who'd like a (from-home) job
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

      Umm.... no.
      sub foo {
          my $baz = 12 if @_;
          print "$baz\n";
          $baz++;
      }
      
      foo(1);
      foo();
      foo();
      foo();
      foo(1);
      foo();
      foo();
      foo();
      
      Produces
      12
      
      1
      2
      12
      
      1
      2
      
      You don't really think I'd not check, do you? :)
        If $baz isn't being reallocated on the second loop iteration, why does the second test print out a blank line (presumably corresponding to an undef $baz) instead of "13"?

        (When I look at the results above, it doesn't give what I'd expect whether $baz is being reallocated every time, or whether it's being reallocated only when @_ has elements in it. I don't know why...)

        Update: Thanks, whoever you are :) That makes a lot of sense.

        Alan

        As for the original post, perhaps you're testing for the wrong phenomenon.

        #!/usr/bin/perl use strict; sub foo { my($bar) = @_; print "foo: $bar\n"; ++$bar; } foo(1); foo(); foo(); foo(); foo(1); foo(); foo(); foo();

        Produces:

        foo: 1 foo: foo: foo: foo: 1 foo: foo: foo:

        So the empty @_ does reset the var, which was I think your original assertion.

        Matt

        Update: Elian is right. That's what I get for posting pre-coffee. His original point involved a conditional assignment. I suppose if there's a moral to this mini-thread it is to make your parameter assignments mandatory unless you really are intending to keep old values around. :-(

        Ah, in my testing, I didn't use enough empty-@_ tests.

        _____________________________________________________
        Jeff[japhy]Pinyan: Perl, regex, and perl hacker, who'd like a (from-home) job
        s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;