Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

perl closures and $_

One of the first things I try to learn in an unfamiliar programming language is how it handles closures. Their semantics are often intertwined with how the language handles scopes and various other tricky bits so understanding them reveals several other aspects of the language. Plus, closures are a really powerful construct and often times cut down on the amount of boilerplate I have to type. So I was messing around with perl closures and I stumbled upon a little gotcha:

my @closures;
foreach (1..3) {
  # create some closures
  push @closures, sub { say "I will remember $_"; };
}
foreach (@closures) {
  # call the closures to see what they remember
  # the result is not obvious
  &{$_}();
}

When I wrote the above code I was expecting to see

I will remember 1
I will remember 2
I will remember 3

but instead I got I will remember CODE(0x986c1f0).

The above experiment revealed that $_ is very context dependent and if it appears in a closure then it's value is not fixed at the point of the closure's creation. It behaves more like a reference. What other gotchas should I be aware of when creating closures in perl?

like image 917
David K. Avatar asked Jan 12 '11 04:01

David K.


People also ask

What is closure in Perl?

Closure is one of the important concepts in Perl. Closure is a computer term with an accurate but a hard to explain meaning. It is often referred as a function that can be stored as a variable, which has a special ability to access other variables local to the scope it was created in.

Why do we use closures?

Closures are useful because they let you associate data (the lexical environment) with a function that operates on that data. This has obvious parallels to object-oriented programming, where objects allow you to associate data (the object's properties) with one or more methods.

Are closures functional?

Introduction to JavaScript closures. In JavaScript, a closure is a function that references variables in the outer scope from its inner scope. The closure preserves the outer scope inside its inner scope. To understand the closures, you need to know how the lexical scoping works first.

Are closures objects?

Closures are a poor man's object." At that moment, Anton became enlightened. The point is that objects and closures are two ways of looking at a thing. In a nutshell, objects are data with behaviour, whereas closures are behaviour with data.


2 Answers

$_ is a global variable and should not be used in closure. Before using it assign this to a lexically scoped variable as shown bewlow. This will produce expected o/p.

#!/usr/bin/perl -w

use strict;
my @closures;


foreach (1..3) {
   my $var = $_;
   push @closures, sub { print "I will remember $var"; };
}

foreach (@closures) {
  $_->();
  print "\n";
}
like image 37
Sachin Hindlekar Avatar answered Sep 19 '22 05:09

Sachin Hindlekar


Closures only close over lexical variables; $_ is normally a global variable. In 5.10 and above, you can say my $_; to have it be lexical in a given scope (though in 5.18 this was retroactively declared to be experimental and subject to change, so better to use some other variable name).

This produces the output you expected:

use strict;
use warnings;
use 5.010;
my @closures;
foreach my $_ (1..3) {
  # create some closures
  push @closures, sub { say "I will remember $_"; };
}
foreach (@closures) {
  # call the closures to see what they remember
  # the result is not obvious
  &{$_}();
}
like image 60
ysth Avatar answered Sep 22 '22 05:09

ysth