in reply to Re^3: Wrong Error Message When Testing for Failure of Constructor
in thread Wrong Error Message When Testing for Failure of Constructor
Ultimately, my preferred code for this would be something like
my $self = bless deep_copy( \%default_values ), $class;where deep_copy takes a reference as argument and returns a reference to a deep copy of it.
I struggled with this some more but, as long as my default values were stored in a hash referenced by the testing subroutine, kept coming up with the same problem. Here's a little program I wrote which takes all the OO stuff out and demonstrates that, contrary to my hope/expectation, %default_values does indeed get transformed over a series of code blocks.
#!/usr/local/bin/perl use strict; use warnings; use Data::Dumper; my $count = 0; my %default_values = ( SUBJECT => 'Subject (<= 44 characters) goes here', AUTHOR => { NAME => 'A. U. Thor', CPANID => 'AUTHOR', WEBSITE => 'http://a.galaxy.far.far.away/modules', EMAIL => 'a.u.thor@a.galaxy.far.far.away', }, ); compare( { %default_values }, { 'NAME' => 'ABC::Alpha', 'AUTHOR' => { NAME => 'James E Keenan', EMAIL => 'jkeenancpan.org', }, } ); compare( { %default_values }, { 'NAME' => 'ABC::Alpha', 'AUTHOR' => { NAME => 'James E Keenan', CPANID => 'JKEENAN', }, } ); print "\nFinished\n"; sub compare { print "\nStart TEST ", ++$count, "----------\n\n"; my ($dvref, $paramsref) = @_; print Dumper ($dvref, $paramsref); my %dv = %{ $dvref }; my %parameters = %$paramsref; foreach my $param ( keys %parameters ) { if ( ref( $parameters{$param} ) eq 'HASH' ) { foreach ( keys( %{ $parameters{$param} } ) ) { $dv{$param}{$_} = $parameters{$param}{$_}; } } else { $dv{$param} = $parameters{$param}; } } print Dumper (\%dv); }
Note that what is dumped for $dvref the second time around differs from what the first time.
I have, however, found a solution: Localize %default_values within a subroutine and have that sub return a reference to that hash. The above program gets transformed into:
compare( default_values(), { 'NAME' => 'ABC::Alpha', 'AUTHOR' => { NAME => 'James E Keenan', EMAIL => 'jkeenancpan.org', }, } ); compare( default_values(), { 'NAME' => 'ABC::Alpha', 'AUTHOR' => { NAME => 'James E Keenan', CPANID => 'JKEENAN', }, } ); sub default_values { my %default_values = ( SUBJECT => 'Subject (<= 44 characters) goes here', AUTHOR => { NAME => 'A. U. Thor', CPANID => 'AUTHOR', WEBSITE => 'http://a.galaxy.far.far.away/modules' +, EMAIL => 'a.u.thor@a.galaxy.far.far.away', }, ); return { %default_values }; } }
The constructor is transformed in this manner:
my $self = ref($class) ? bless( default_values(), ref($class) ) : bless( default_values(), $class );
So, instead of the constructor blessing a reference to a hash of default values, it blesses the return value of a subroutine where that value is in turn a reference to the hash of default values.
As I said at the outset, this example was a stripped-down version of a problem I was facing with the ongoing development of a module I maintain. Ironically, the solution above is the solution which the original module author (Geoff Avery) came up with in earlier versions of the module (ExtUtils::ModuleMaker). Plus ça change ....
Thanks again.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^5: Wrong Error Message When Testing for Failure of Constructor
by tlm (Prior) on Jul 24, 2005 at 01:22 UTC | |
by jkeenan1 (Deacon) on Jul 24, 2005 at 01:40 UTC |