of course you could also put only those subs inside an extra block together with the closure var.
Ok, I see what you mean. Personally, I tend to think of closures as something you can make multiple instances of (sub foo { my $x=0; return sub {$x++} }), but if the code you showed was in a block, then I guess that can fit the definition of a closure too, since the subs are then the only thing to hold references to the variables.
| [reply] [d/l] [select] |
> Personally, I tend to think of closures as something you can make multiple instances of
That's a further concept, building on top of closures.
In what you show foo is a "generator" returning an anonymous sub, which is indeed enclosing $x ... but that's not necessary for a closure.
A "closure" is the combination of a sub and "enclosed"° vars from the outer scope.
you don't need generators for closures...
see also Closure (computer programming) :
"Operationally, a closure is a record storing a function together with an environment."
But it's true that many - including me - often simply say "closure" for the "closure function"
> but if the code you showed was in a block, then I guess that can fit the definition of a closure too
an explicit block is just cosmetics, since the file-scope acts as a default block.
> since the subs are then the only thing to hold references to the variables.
That's bit confusing ... a sub will only hold reference to a variable form a surrounding scope if it's enclosed, i.e. explicitly used. You don't need a block to enforce this.
Consider this example, where the second bar() will fail because there is no explicit use of $var, just a symbolic reference.
Since it's not bound - here realized as the scratch pads of the sub increasing the ref-count - it can be destroyed.
NB: I just need the block here because all calls are in the same file.
use v5.12;
use warnings;
use Data::Dump qw/pp dd/;
{
my $var = 42;
sub foo {
warn $var;
}
sub bar {
eval 'warn $var';
}
foo();
bar();
}
foo();
bar();
42 at c:/tmp/pm/closure_demo.pl line 9.
42 at (eval 1) line 1.
42 at c:/tmp/pm/closure_demo.pl line 9.
Variable "$var" is not available at (eval 2) line 1.
Use of uninitialized value $var in warn at (eval 2) line 1.
Warning: something's wrong at (eval 2) line 1.
updates
°) lexical vars in this case, package vars are just globally available... | [reply] [d/l] [select] |
an explicit block is just cosmetics, since the file-scope acts as a default block.
I'd be surprised if the definition of a closure really is that broad, but I don't have the time to research in detail right now. Update: To clarify: I did skim the Wikipedia article before posting and it makes it pretty clear to me that definitions differ, so I suspect that simply our definitions differ. In the context of Perl, perlglossary does say that a closure is "An anonymous subroutine that, when a reference to it is generated at runtime, keeps track of the identities of externally visible lexical variables, even after those lexical variables have supposedly gone out of scope."
Update 2: Ok, so I did do at least a little bit more research. The above definition of a closure is repeated across much of the Perl documentation, but then there's Persistent variables with closures that shows a named sub that is closer to what you showed. So like I said, I guess definitions differ.
| [reply] [d/l] |
> In what you show foo is a "generator" returning an anonymous sub,
I have to somehow correct myself, because I can't find this definition of "generator" anymore. Maybe I saw it in HOP.
I tried to reference WP, but Generator (computer programming) refers to something different. That's the yield concept from Python (gather-take in Raku), which is not a closure maker, but syntactic sugar for an iterator.
Looks like the programming world is taking over the Python interpretation, ECMA6 introduced yield too.
| [reply] [d/l] [select] |