Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
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 romping around the Monastery: (7)
As of 2014-11-23 05:07 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My preferred Perl binaries come from:














    Results (128 votes), past polls