in reply to Re: understanding closures
in thread understanding closures

Brilliant, Closure on Closures did it for me. The summing up in particular...

a closure is a subroutine which wraps around lexical variables that it references from the surrounding lexical scope which subsequently means that the lexical variables that are referenced are not garbage collected when their immediate scope is exited

This story has a sad end, however. To test my knowledge new-found knowledge, I wrote the following.

sub make_two_counters { my $count = 0; return sub{ $count++ }, sub{ $count+=10 } } my ($counter_plus_one, $counter_plus_ten) = make_two_counters(); print $counter_plus_one->() . "\n"; print $counter_plus_one->() . "\n"; print $counter_plus_ten->() . "\n"; print $counter_plus_one->() . "\n"; print $counter_plus_one->() . "\n"; __OUTPUT__ 0 1 12 12 13
I was expecting this to print 0,1,11,12,13 - on the grounds that my two anonymous subs would be saving the same reference to the lexical ($count). But it seems to have merged two of my adds in together!! Help.

BTW: Thanks for all the replies ++

---
my name's not Keith, and I'm not reasonable.

Replies are listed 'Best First'.
Re^3: understanding closures
by Limbic~Region (Chancellor) on Sep 23, 2005 at 14:04 UTC
    reasonablekeith,
    Here is a clue - what happens when you forget about closures and run the following code?
    #!/usr/bin/perl use strict; use warnings; my $cnt = 0; print $cnt++, "\n"; print $cnt++, "\n"; print $cnt += 10, "\n"; print $cnt++, "\n"; print $cnt++, "\n";
    The ++ operator (see perlop) first retrieves the current value and then increments the value when used as post-increment.
    • Start at 0
    • Return 0, make $cnt 1
    • Return 1, make $cnt 2
    • Return 2 + 10, make $cnt 12
    • Return 12, make $cnt 13
    • Return 13, make $cnt 14

    Cheers - L~R

Re^3: understanding closures
by dragonchild (Archbishop) on Sep 23, 2005 at 14:35 UTC
    I was expecting this to print 0,1,11,12,13 - on the grounds that my two anonymous subs would be saving the same reference to the lexical ($count). But it seems to have merged two of my adds in together!! Help.

    Your closures are correct. However, you're confused about something else. $count++ will return the value of $count, then add 1 to it. $count+=10 will add 10 to count, then return the value of $count.

    Try the following:

    my $count = 0; sub make_two_counters { return sub{ $count++ }, sub{ $count+=10 } } my ($counter_plus_one, $counter_plus_ten) = make_two_counters(); print $counter_plus_one->() . " ($count)\n"; print $counter_plus_one->() . " ($count)\n"; print $counter_plus_ten->() . " ($count)\n"; print $counter_plus_one->() . " ($count)\n"; print $counter_plus_one->() . " ($count)\n"; __OUTPUT__ 0 (1) 1 (2) 12 (12) 12 (13) 13 (14)

    Does that help?


    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
Re^3: understanding closures
by Anonymous Monk on Sep 23, 2005 at 14:05 UTC
    They are sharing the same lexical. What confuses you is the fact that you are doing post-increment. The result of $count++ is the old value of $count. Change that line to ++$count, and try again.
      Yup, you're right. I was too busy wondering about closures to spot that one. Not that this is an excuse. :(

      Thanks everyone.

      ---
      my name's not Keith, and I'm not reasonable.