Confused about closures

Do you have a question? Post it now! No Registration Necessary.  Now with pictures!

Threaded View


Following's an extract from Perl FAQ 7.13 (closures):

    Closures are often used for less esoteric purposes. For example,
    you want to pass in a bit of code into a function:
            my $line;
            timeout( 30, sub { $line = <STDIN> } );
    If the code to execute had been passed in as a string, '$line =
    <STDIN>', there would have been no way for the hypothetical
    function to access the lexical variable $line back in its

I'm not clear about what's being said here...why would timeout need to
access $line here at all? What would be wrong with:


What's the real, "less esoteric", use of the closure being described
here? Pls. help I missing something obvious?

Thanks in advance,

P.S: Pardon me if this is something silly which's escaping
overworked. Pls. bear...

Re: Confused about closures

Quoted text here. Click to load it

   I think what perlfaq7 is trying to say is that timeout() is just a
hypothetical function that someone might need to create: nothing more
than a function that takes a subroutine as an argument.

   Instead of passing in sub { ... } as an argument to a function,
sometimes people will pass in a string containing code, to be eval()ed
in the function.

Quoted text here. Click to load it

   If you did that, then $line wouldn't be populated.  Apparently the
person who created the hypothetical timeout() function wants to
populate $line with input taken from STDIN.  Your way
( timeout(30,scalar(<STDIN>)) ) wouldn't do that.  Not only that, but
your way would execute scalar(<STDIN>) right before the timeout()
function was called, instead of inside it.

Quoted text here. Click to load it

   I think perlfaq7 means it's "less esoteric" when compared to
passing in the code as a string, like this:

      timeout( 30, '$line = <STDIN>' );

If a programmer wants to pass in code to execute inside a function
(during the function's execution), sometimes they will pass the code
into the function as a string, and then eval() it in the function.

   However, the "less esoteric" way of doing it is to pass it in as a
subroutine reference itself -- that is, instead of passing in '$line =
<STDIN>', you pass in sub { $line = <STDIN> }.  That way the $line
variable can refer to the one that was declared (with "my") right
before the call to timeout().

   In other words, when executing the passed-in code with:

      my $line;
      timeout( 30, sub { $line = <STDIN> } );

the $line variable we see here gets populated.  But with:

      my $line;
      timeout( 30, '$line = <STDIN>' );

then the $line variable we see here WON'T get populated.  Instead, a
$line variable visible in the timeout() function will get populated
instead (when the code gets eval()ed in the timeout() function).

   So if you want the $line variable (the one we're seeing declared
before the call to timeout()) to be populated, using the closure is
the better way to do it.

   I hope that helps, Chaitanya.


   -- Jean-Luc

Re: Confused about closures

Krishna Chaitanya wrote:
Quoted text here. Click to load it

Two things.  First of all, that would wait (potentially forever) for a
line to be read from STDIN, *before* timeout got executed.  This would
presumably defeat the purpose of having a subroutine named timeout.  But
this has nothing to do with closures.

Second, if you want the next line in STDIN to be thrown away, that would
be fine.   But presumably you want it to be assigned to $line, otherwise
you wouldn't be assigning it to $line.


Site Timeline