in reply to Help with the concept of closures.

The critical thing is that even though $item seems to have gone out of scope once shoppingList() has returned, the code reference it returns has a copy of $item in it. This copy retains the value $item had at the time that shoppingList returned the reference.

So you can call each of these references as many times as you wish, and the first thing it tells you you need will always be the same as what you gave the routine when you created the code reference with shoppingList();



--Bob Niederman, http://bob-n.com

Replies are listed 'Best First'.
Re: Re: Help with the concept of closures.
by chromatic (Archbishop) on Jul 06, 2003 at 02:13 UTC

    It's not a copy. It's the same variable.

    sub make_closures { my $value = shift; return sub { $value++ }, sub { print "$value\n" }, sub { $value-- } +; } my ($increment, $display, $decrement) = make_closures( 3 ); $display->(); $increment->(); $display->(); $decrement->(); $display->();

      Nope. Each coderef (set of coderefs in your example - it's the time that the lexical is in scope that matters) has it's own copy.

      sub make_closures { my $value = shift; return sub { $value++ }, sub { print "$value\n" }, sub { $value-- }; } my ($increment, $display, $decrement) = make_closures( 3 ); print "first\n"; $display->(); $increment->(); $display->(); $decrement->(); $display->(); my ($increment2, $display2, $decrement2) = make_closures( 9 ); print "second\n"; $display2->(); $increment2->(); $display2->(); $decrement2->(); $display2->(); print "first again\n"; $display->(); $increment->(); $display->(); $decrement->(); $display->();

      Result:

      first
      3
      4
      3
      second
      9
      10
      9
      first again
      3
      4
      3
      

      That's why it needs to be lexical.



      --Bob Niederman, http://bob-n.com

        I suspect we mean different things by the word "copy".

        Because lexical variables live in scratchpads and because a closure carries around the scratchpad where it was created, I say that a closure does not make a new copy of the variable.

        Because a new scratchpad is created on each scope entry and the closures returned bind to the new scratchpad, you say that a closure does copy the variable.

        I don't think "copy" is the right word, but I understand what you're saying and the effect is indeed accurate.