NAME
Closure::Explicit - check coderefs for variable capture
VERSION
version 0.002
SYNOPSIS
{
sub
new {
my
$class
=
shift
;
bless
{},
$class
}
sub
method {
my
$self
=
shift
;
"In method\n"
}
}
my
$self
= Example->new;
# This will raise an exception due to the reference to $self
eval
{
my
$code
= callback {
$self
->method;
};
};
# This will not raise the exception because $self is whitelisted
my
$code
= callback {
$self
->method;
} [
qw($self)
];
# This will wrap the coderef so we can pass a weakened copy of $self
my
$code
= callback {
my
$self
=
shift
;
$self
->method;
}
weaken
=> [
qw($self)
];
DESCRIPTION
Attempts to provide some very basic protection against unintentional capturing of lexicals in a closure.
For example, code such as the following risks creating cycles which mean the top-level object is never freed:
sub
some_method {
my
$self
=
shift
;
$self
->{callback} =
sub
{
$self
->other_method }
}
and this can in turn lead to memory leaks.
API STABILITY
The main "callback" function is not expected to change in future versions, so as long as you use this:
to import the function into your local namespace, or fully-qualify it using
Closure::Explicit::callback { ... }
then you should have no problems with future versions of this module.
However, it is highly likely that a future version will also start exporting a differently-named function with a better interface.
EXPORTS
callback
Checks the given coderef for potential closure issues, raising an exception if any are found and returning the coderef (or a wrapped version of it) if everything is okay.
The first parameter is the block of code to run. This is protoyped as &
so you can replace the usual 'sub { ... }' with 'callback { ... }'. If you already have a coderef, you can pass that using &callback($code, ...)
, but please don't.
Remaining parameters are optional - you can either pass a single array, containing a list of the names of the variables that are safe to capture:
callback {
"$x\n"
} [
qw($x)
];
or a list of named parameters:
weaken => [...] - list of variable names which will be copied, weakened via "weaken" in Scalar::Util, then prepended to the parameter list available in @_ in your code block
allowed => [...] - list of variable names to ignore if used in the code, same behaviour as passing a single arrayref
For example, a method call might look like this:
my
$code
= callback {
my
$self
=
shift
;
$self
->method(
@_
);
}
weaken
=> [
qw($self)
];
although curry::weak would be a much cleaner alternative there:
my
$code
=
$self
->curry::weak::method;
You can mix weaken
and allowed
:
my
$x
= 1;
my
$code
= callback {
shift
->method(++
$x
);
}
weaken
=> [
qw($self)
],
allowed
=> [
qw($x)
];
lint
Runs checks on the given coderef. This is used internally and not exported, but if you just want to get a list of potential problems for a coderef, call this:
my
@errors
= lint(
$code
,
allowed
=> [
qw($x)
]);
It's unlikely that the weaken
parameter will work when calling this function directly - this may be fixed in a future version.
SEE ALSO
curry - provides a convenient interface for creating callbacks
PadWalker - does most of the real work behind this module
Test::RefCount - convenient testing for reference counts, makes cycles easier to detect in test code
Devel::Cycle - reports whether cycles exist and provides useful diagnostics when any are found
INHERITED METHODS
- Exporter
-
as_heavy, export, export_fail, export_ok_tags, export_tags, export_to_level, import, require_version
AUTHOR
Tom Molesworth <cpan@entitymodel.com>
LICENSE
Copyright Tom Molesworth 2012-2013. Licensed under the same terms as Perl itself.