Matthew Simon Cavalletto

NAME

DBIx::SQLEngine::Utility::CloneWithParams - Nifty Cloner

SYNOPSIS

  use DBIx::SQLEngine::Utility::CloneWithParams;
  
  $clone = clone_with_parameters( $string, @replacements );
  $clone = clone_with_parameters( \@array, @replacements );
  $clone = clone_with_parameters( \%hash, @replacements );

DESCRIPTION

This package provides a function named clone_with_parameters() that makes deep copies of nested data structures, while making replacements in key places.

clone_with_parameters

  $clone = clone_with_parameters( $reference, @replacements );

This function makes deep copies of nested data structures, with object reblessing and loop detection to avoid endless cycles. (The internals are based on clone() from Clone::PP.)

It's one distinctive behavior is that if a data structure contains references to the special numeric Perl variables $1, $2, $3, and so forth, when it is cloned they are replaced with a set of provided parameter values. It also replaces stringified versions of those references embedded in scalar values.

An exception is thrown if the number of parameters provided does not match the number of special variables referred to.

Limitations:

  • This will not properly copy tied data.

  • Using this to clone objects will only work with simple objects that don't do much preprocessing of the values they contain.

Examples:

  • Here's a simple copy of a string with embedded values to be provided by the caller:

      my $template = \$1 . '-' . \$2;
      my $clone = clone_with_parameters( $template, 'Foozle', 'Basil' );
      ok( $clone, 'Foozle-Basil' );
  • Here's a simple cloning of an array with values to be provided by the caller:

      my $template = [ \$1, '-', \$2 ];
      my $clone = clone_with_parameters( $template, 'Foozle', 'Basil' );
      is_deeply( $clone, [ 'Foozle', '-', 'Basil' ] );
  • Here's a simple cloning of a hash with key values to be provided by the caller:

      my $template = { foo => \$1, bar => \$2 }; 
      my $clone = clone_with_parameters( $template, 'Foozle', 'Basil' );
      is_deeply( $clone, { foo => 'Foozle', bar => 'Basil' } );
  • Templates to be copied can contain nested data structures, and can use paramters multiple times:

      my $template = { foo => \$1, bar => [ \$2, 'baz', \$2 ] }; 
      my $clone = clone_with_parameters( $template, 'Foozle', 'Basil' );
      is_deeply( $clone, { foo=>'Foozle', bar=>['Basil','baz','Basil'] } );
  • Although hash keys are automatically stringified, they still are substituted:

      my $template = { foo => 'bar', \$1 => \$2 }; 
      my $clone = clone_with_parameters( $template, 'Foozle', 'Basil' );
      is_deeply( $clone, { foo => 'bar', Foozle => 'Basil' } );
  • Objects can be copied to produce properly-blessed clones:

      package My::SimpleObject;
    
      sub new { my $class = shift; bless { @_ } $class }
      sub foo { ( @_ == 1 ) ? $_[0]->{foo} : ( $_[0]->{foo} = $_[1] ) }
      sub bar { ( @_ == 1 ) ? $_[0]->{bar} : ( $_[0]->{bar} = $_[1] ) }
    
      package main;
      use DBIx::SQLEngine::Utility::CloneWithParams;
    
      my $template = My::SimpleObject->new( foo => \$1, bar => \$2 ); 
      my $clone = clone_with_parameters( $template, 'Foozle', 'Basil' );
      isa_ok( $clone, 'My::SimpleObject' );
      ok( $clone->foo, 'Foozle' );
      ok( $clone->bar, 'Basil' );

    If the class itself imports clone_with_parameters(), it can be called as a method instead of a function:

      package My::SimpleObject;
      use DBIx::SQLEngine::Utility::CloneWithParams;
      ...
      
      package main;
    
      my $template = My::SimpleObject->new( foo => \$1, bar => \$2 ); 
      my $clone = $template->clone_with_parameters( 'Foozle', 'Basil' );
      ...

safe_eval_with_parameters

  @results = safe_eval_with_parameters( $perl_code_string );

Uses the Safe package to eval the provided code string. Uses a compartment which shares the same numeric variables, so that values evaluated this way can then be cloned with clone_with_parameters.

SEE ALSO

See DBIx::SQLEngine for the overall interface and developer documentation.

See DBIx::SQLEngine::Docs::ReadMe for general information about this distribution, including installation and license information.