Data::Decycle - (Cyclic|Circular) reference decycler
$Id: Decycle.pm,v 0.1 2010/08/22 19:58:45 dankogai Exp dankogai $
use Data::Decycle; # none of them leak { my $guard = Data::Decycle->new; add $guard my $cyclic_sref = \my $dummy; $cyclic_sref = \$cyclic_sref; add $guard my $cyclic_aref = []; $cyclic_aref->[0] = $cyclic_aref; add $guard my $cyclic_href = {}; $cyclic_href->{cyclic} = $cyclic_href; } # or register all at once { my $guard = Data::Decycle->new( my $cyclic_sref = \my $dummy, my $cyclic_aref = [], my $cyclic_href = {} ); $cyclic_sref = \$cyclic_sref; $cyclic_aref->[0] = $cyclic_aref; $cyclic_href->{cyclic} = $cyclic_href; } # if you have PadWalker, you can decycle closures, too. { my $guard = Data::Decycle->new; my $cref; $cref = sub{ $_[0] <= 1 ? 1 : $_[0] * $cref->($_[0] - 1) }; $guard->add($cref); print $cref->(10); } # you can also cope with circular references explicitly use Data::Decycle ':all'; my $obj = bless {}, 'Dummy'; $obj->{me} = $obj; print may_leak($obj); # true weaken_deeply($obj); print may_leak($obj); # false print has_cyclic_ref($obj); # true decycle_deeply($obj); print $obj->{me} == undef; # true
Perl programmers love to hate cyclic References, or circular references. It easly leaks out of perl's reference-counter based garbage collection and stays there until perl exits.
Even with the introduction of weak references in Perl 5.8, you still have to tell perl explicitly to weaken references and which reference to weaken is tricky.
use Devel::Peek; use Scalar::Util qw/weaken/; my $obj = {you => $ENV{USER}}; $obj->{me} = $obj; weaken($obj); # wrong weaken($obj->{me}) # right;
In addition to that, weak references do not work with code references.
my $cref; $cref = sub { $_[0] <= 1 ? 1 : $_[0] * $cref->( $_[0] - 1 ) }; print $cref->(10); weaken($cref); # does undef($cref) print $cref->(10); # goodbye
This module offers something easier than that.
See the source :-p
Okay, I'll be nicer. Consider the code below again.
{ my $guard = Data::Decycle->new( my $cyclic_sref = \my $dummy, my $cyclic_aref = [], my $cyclic_href = {} ); $cyclic_sref = \$cyclic_sref; $cyclic_aref->[0] = $cyclic_aref; $cyclic_href->{cyclic} = $cyclic_href; }
What happens when it reaches out of the block? $guard will surely be DESTROY()'ed. So it is guaranteed to trigger $guard->DESTROY. And in there it applys decycle_deeply to each reference registered.
decycle_deeply
Simple, huh?
None except for core modules.
To handle code references correctly, you need to have PadWalker installed.
None by default. Please import explicitly.
see "SYNOPSIS"
checks if $obj may leak. That is, contains a circular reference that is not weak.
$obj
checks if cyclic reference exists in $obj.
undefs all duplicate references in $obj thus breaks all cyclic reference. Unlike weaken_deeply, it decycles even code references. You shouldn't call it yourself; let decycle take care of it.
undef
weaken_deeply
decycle
weaken all duplicate references in $obj. Unlike decycle_deeply it leaves code references intact. So you can safely call it but you are at your own if $obj contains a code reference that cycles.
Consider the code below:
my $fact; $fact = sub { $_[0] <= 1 ? 1 : $_[0] * $fact->($_[0]-1) };
This leaks since $fact is now a cyclic reference. with the combination of recsub and $CALLEE, you can rewrite the code as:
recsub
$CALLEE
my $fact = recsub { $_[0] <= 1 ? 1 : $_[0] * $CALLEE->($_[0]-1) };
To use this feature, you should import both recsub and $CALLEE as:
use Data::Decycle qw(recsub $CALLEE);
or import just recsub and define your own $CALLEE:
use Data::Decycle qw(recsub); our $CALLEE;
Unlike the previous example, this one dow not leak. See Sub::Recursive for more complicated examples such as mutually recursive subrefs.
Dan Kogai, <dankogai+cpan at gmail.com>
<dankogai+cpan at gmail.com>
Please report any bugs or feature requests to bug-data-decycle at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Data-Decycle. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
bug-data-decycle at rt.cpan.org
You can find documentation for this module with the perldoc command.
perldoc Data::Decycle
You can also look for information at:
RT: CPAN's request tracker
http://rt.cpan.org/NoAuth/Bugs.html?Dist=Data-Decycle
AnnoCPAN: Annotated CPAN documentation
http://annocpan.org/dist/Data-Decycle
CPAN Ratings
http://cpanratings.perl.org/d/Data-Decycle
Search CPAN
http://search.cpan.org/dist/Data-Decycle/
You need this if you want to handle code references properly. When you don't have one this module simply does nothing when it encounters them.
Good for inspection -- rather overkill. Decycling features missing.
Copyright 2010 Dan Kogai.
This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.
See http://dev.perl.org/licenses/ for more information.
To install Data::Decycle, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Data::Decycle
CPAN shell
perl -MCPAN -e shell install Data::Decycle
For more information on module installation, please visit the detailed CPAN module installation guide.