in reply to Closures and scope of lexicals

In the for my ... case, the loop lexical is implicitly scoped to inside the for body. At the point it reaches the end of the block, the lexical goes out of scope and perl notes that there's an external reference to it and allocates a new one. (This is true for all lexicals and blocks, not specific to for.)

In the second case, the lexical never goes out of scope, so all closures reference the same scalar, just as if you did push @subrefs, sub { print $i }, sub { print $i }; in the "good" code it would produce 112233.

--
A math joke: r = | |csc(θ)|+|sec(θ)| |-| |csc(θ)|-|sec(θ)| |

Replies are listed 'Best First'.
Re^2: Closures and scope of lexicals
by haj (Vicar) on Oct 30, 2024 at 20:54 UTC

    Yeah, thanks for the explanation. The key is "all closures reference the same scalar". Somehow I assumed that the closure would use the current value of the scalar (in a new slot). Thanks also to LanX and Hippo for their (similar) explanations!

      I assumed that the closure would use the current value of the scalar

      Definitely not. If that were the case, then calling it "binding" (or "closing over") would make no sense. The point is that it binds to the variable in the enclosing scope. So both the sub and any other code with access to that variable can change it.

      sub make_private_var_with_accessors { my $var; ( sub { my $val = $var; $val }, # getter sub { $var = shift } # setter ) } my($get,$set) = make_private_var_with_accessors(); $set->(42); print "=".$get->()."\n";
      And it's but a hop and a skip to turn that into a POPO class:
      { package PrivateVariable; sub new { my $pkg = shift; my $var; bless { get => sub { my $val = $var; $val }, set => sub { $var = shift }, }, $pkg } sub get { $_[0]->{get}->() } sub set { $_[0]->{set}->($_[1]) } } my $pv = new PrivateVariable; $pv->set(666); print "=".$pv->get()."\n";
      Today's latest and greatest software contains tomorrow's zero day exploits.
      You can also create multiple closures which access the same but otherwise private variables.

      Closure-subs have a lot in common with object-methods and the closure-vars act like instance variables.

      Again, please have a look at the HOP book, you won't regret it.

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      see Wikisyntax for the Monastery