Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Default named params with an embedded hash

by neilwatson (Curate)
on Aug 28, 2014 at 19:12 UTC ( #1098910=perlquestion: print w/ replies, xml ) Need Help??
neilwatson has asked for the wisdom of the Perl Monks concerning the following question:

Greetings,

I'm trying to use named parameters with default values. For a normal hash this is simple, but I have a more complex data structure.
#!/usr/bin/perl use strict; use warnings; use feature 'say'; use Data::Dumper; my %valid_inputs = ( one => 1, two => 2 ); validate( valid_inputs => \%valid_inputs, max_record_length => 72, ); sub validate { my %params = ( valid_inputs => { one => 'one', two => 'two', three => 'three', four => 'four', }, max_record_length => 24, @_, ); my $valid_inputs = $params{valid_inputs}; say '@_ ['.Dumper( \@_ ).']'; say '%params ['.Dumper( \%params ).']'; say '%valid_inputs ['.Dumper( \%valid_inputs ).']'; } #EOF Output: @_ [$VAR1 = [ 'valid_inputs', { 'two' => 2, 'one' => 1 }, 'max_record_length', 72 ]; ] %params [$VAR1 = { 'valid_inputs' => { 'two' => 2, 'one' => 1 }, 'max_record_length' => 72 }; ] %valid_inputs [$VAR1 = { 'two' => 2, 'one' => 1 }; ]

Because valid_inputs is a reference it over writes the defaults completely rather than just the same keys as with max_record_length. If make valid_inputs not a refence the final complete hash is scrambled and flat. Is there an elegant solution?

Neil Watson
watson-wilson.ca

Comment on Default named params with an embedded hash
Download Code
Re: Default named params with an embedded hash
by Anonymous Monk on Aug 28, 2014 at 19:25 UTC

      Thanks for this. I wasn’t familiar with the Hash::Merge module, it’s a useful addition to the toolbox.

      In case it helps anyone else, here’s how I got it to work with the OP’s script:

      #! perl use strict; use warnings; use feature 'say'; use Data::Dump 'pp'; use Hash::Merge 'merge'; my %valid_inputs = ( one => 1, two => 2, ); validate( valid_inputs => \%valid_inputs, max_record_length => 72, ); sub validate { my %params = ( valid_inputs => { one => 'one', two => 'two', three => 'three', four => 'four', }, max_record_length => 24, ); Hash::Merge::set_behavior('RIGHT_PRECEDENT'); %params = %{ merge( \%params, { @_ } ) }; say "\%params =\n", pp(\%params); }

      (The only slightly tricky part was turning @_ into a hash reference.) Output:

      12:41 >perl 987_SoPW.pl %params = { max_record_length => 72, valid_inputs => { four => "four", one => 1, three => "three", t +wo => 2 }, } 12:42 >

      I’d call that elegant.

      Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: Default named params with an embedded hash
by Ea (Friar) on Aug 29, 2014 at 21:06 UTC
    While I currently favour hash slices a la Modern Perl, I couldn't quickly figure out how to get the valid_inputs and max_record_length in one line.
    my (%hash) = @_; @{$params{valid_inputs}}{keys $hash{valid_inputs}} = values $hash{valid_inputs}; $params{max_record_length} = $hash{max_record_length} || $params{max_record_length};

    Oh, and thanks again for the steak!

    Sometimes I can think of 6 impossible LDAP attributes before breakfast.

      Hello Ea,

      Using hash slices is a clever strategy here!, and the Modern Perl link is a useful one. I must admit, I’m still trying to get my head around the @{ ... }{ ... } syntax, which is perfectly correct, but looks wrong (to me).

      But this:

      $params{max_record_length} = $hash{max_record_length} || $params{max_record_length};

      makes it impossible to override $params{max_record_length} with a zero value. Easily fixed:

      $params{max_record_length} = $hash{max_record_length} // $params{max_record_length};

      See perlop#Logical-Defined-Or.

      Cheers,

      Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1098910]
Approved by philipbailey
Front-paged by philipbailey
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (9)
As of 2014-09-15 04:38 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite cookbook is:










    Results (145 votes), past polls