Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Respected Monks, Is there a module to save and restore all package variables like this way
use ???; my $tmp = ???save('My::'); ... $My::a = ... push @My::b, ... $My::c{key} = ... ... if (! success) { ???restore($tmp); }
some keywords 'freeze thaw serialize dump restore whole all full package namespace symbols variables'

Replies are listed 'Best First'.
Re: Is there a module to save and restore all package variables
by ikegami (Patriarch) on Aug 03, 2007 at 15:24 UTC

    It seems to me you're heading down the wrong path. If we knew the big picture better (What are these package vars? Why do they need to restore them?), perhaps you could help you better.

    Or maybe it's as simple as moving the variables from the package to a hash or object. Then you could dclone or freeze the hash to make a "backup" of it.

    Here's an implementation that uses a hash:

    use Scope::Guard qw( ); my %state; { my $backup = freeze(\%state); my $sentinel = Scope::Guard->new(sub { %state = %{ thaw($backup) }; }); $state{a} = ...; push @{$state{b}}, ...; $state{c}{key} = ...; if (success) { $sentinel->dismiss(); } }

    The advantage of using Scope::Guard is that the changes to %state will get undone automatically if you return or die before reaching the end of the block.

    Update: Here's the class version:

    { package AtomicState; # yucky name! sub new { my ($class) = @_; return bless({}, $class); } sub transaction { my ($self) = @_; return AtomicState::Transaction->new($self); } } { package AtomicState::Transaction; sub new { my ($class) = @_; my $obj_ref = \$_[1]; my $self = bless([ $obj_ref, undef ], $class); $self->commit(); return $self; } sub start_transaction { my ($self) = @_; my $backup = freeze($self); return AtomicState::Transaction->new($self); } # Multiple commits are allowed. sub commit { my ($self) = @_; $self->[1] = freeze(${$self->[0]}); } # Rolls back to the last commit, the first # being the creation of the the Transaction. sub rollback { my ($self) = @_; ${$self->[0]} = thaw($self->[1]); } sub DESTROY { my ($self) = @_; $self->rollback(); } } my $state = AtomicState->new(); { my $transact = $state->transaction(); $state->{a} = ...; push @{$state->{b}}, ...; $state{c}->{key} = ...; if (success) { $transact->commit(); } }
      Thank you, ikegami, I didn't know at all about modules like Scope::Guard and other Scope...

      But, most likely, I should use direct package namespace in any case because of it seems that there will be many code inclusions in project files throw do &| eval &| require &| use. Fully qualified variables, imho, is most consistent way to make global environment which will be accessible in any file of such project?
Re: Is there a module to save and restore all package variables
by marto (Cardinal) on Aug 03, 2007 at 14:51 UTC
    Perhaps Storable is what you need.

    Hope this helps

    Martin
      but can storable freeze glob ?
        Ah, not according to the documentation:

        "You can't store GLOB, FORMLINE, etc.... If you can define semantics for those operations, feel free to enhance Storable so that it can deal with them."

        Martin