Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Re: Re: Unusual Closure Behaviour

by sierrathedog04 (Hermit)
on Jul 12, 2001 at 21:11 UTC ( [id://96116]=note: print w/replies, xml ) Need Help??


in reply to Re: Unusual Closure Behaviour
in thread Unusual Closure Behaviour

It is a bug. As it is written in the tractate Camel III 4:132:
Lexicals are hidden from any subroutine called from their scope. This is true even if the same subroutine is called from itself or elsewhere—each instance of the subroutine gets its own "scratchpad" of lexical variables.
$x is clearly a lexical. Its scope is inside foo. Yet each instance of foo is not getting its own scratchpad of lexical variables. Hence, we have a creepy crawly thing of uncertain appeal...a bug.

Update 2: One might argue that the anomalous behavior of $x is consistent with the above dictum, because the subroutine foo is not being called from scope of $x. However, when the Perl wise ones write that lexicals are hidden from any subroutine called from their scope, it means even if they are called from their scope.

If a lexical is hidden from subroutines called from inside its own scope, then how much more so must it be hidden from subroutines called from outside its own scope.

As Abigail has taught, conditionally declaring lexicals for use in subroutines is an example of "an ox that is known to gore," i.e., its behavior is going to be ambiguous. Even though it is legal to release such an ox and let it run around and possibly damage a neighbor's code, let us instead "build a fence around the Law" and only declare lexical variables in subroutines unconditionally, outside of conditional branching such as 'my $x if 0'.

(previous updates effaced)

Replies are listed 'Best First'.
Re: Unusual Closure Behaviour
by Abigail (Deacon) on Jul 13, 2001 at 14:26 UTC
    Well, technically what is happening is not violating Camel III. See, it *does* get its own scratchpad, which can be quickly checked by:
    #!/opt/perl/bin/perl -w use strict; sub foo; sub foo { return unless $_ [0]; my $x if 0; print ++ $x, " "; foo $_ [0] - 1; } foo 1; print "\n"; foo 2; print "\n"; foo 3; print "\n"; foo 4; print "\n"; __END__ 1 2 1 3 2 1 4 3 2 1
    Scary, isn't? When the subroutine recurses, it notices there is still a reference to $x and hence it will create a new scratchpad. But when there is no reference, it will reuse an old scratchpad....

    I do agree that using my in this way doesn't tend to lead to well understood code. I wouldn't go as far as to say it's never useful, but such cases will be very rare and it's not a technique I would teach in my classes.

    -- Abigail

        This place needs you.

        So true.

        What happens here? Does this mean that each scratchpad is persistent at its recursion level?

        use strict; sub foo; sub foo { return unless $_ [0]; my $x if undef; print ++ $x, " "; foo $_ [0] - 1; } foo 1; print "\n"; foo 2; print "\n"; foo 3; print "\n"; foo 7; print "\n"; foo 11; print "\n"; foo 9; print "\n"; foo 15; print "\n"; __END__ 1 2 1 3 2 1 4 3 2 1 1 1 1 5 4 3 2 2 2 2 1 1 1 1 6 5 4 3 3 3 3 2 2 7 6 5 4 4 4 4 3 3 2 2 1 1 1 1
        perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'
      Have you tried this?
      #!/usr/bin/perl use strict; sub foo; sub foo { return unless $_ [0]; my $x if undef; print ++ $x, " "; foo $_ [0] - 1; } foo 29; print "\n";
      It prints:

      1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

      Hum...

         Deprecated use of my() in false conditional at - line 6.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://96116]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (6)
As of 2024-04-20 00:33 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found