Beefy Boxes and Bandwidth Generously Provided by pair Networks RobOMonk
Think about Loose Coupling
 
PerlMonks  

Re^3: Benifits of using hash rather than number of variables?

by JavaFan (Canon)
on Jul 21, 2011 at 13:39 UTC ( #915867=note: print w/ replies, xml ) Need Help??


in reply to Re^2: Benifits of using hash rather than number of variables?
in thread Benifits of using hash rather than number of variables?

That doesn't really work for named parameters, specially not if some parameters are optional. Unless you're going to do something unwieldy like:

sub whatever { unless (@_) { my %params = (key1 => undef, key2 => undef, key3 => undef,); lock_keys %params; return \%params; } my %params = %{+shift}; ... sub body using named parameters ... } my $whatever_params = whatever(); $whatever_params->{key1} = $value1; $whatever_params->{key2} = $value2; $whatever_params->{key3} = $value3; whatever $whatever_params;


Comment on Re^3: Benifits of using hash rather than number of variables?
Download Code
Re^4: Benifits of using hash rather than number of variables?
by duelafn (Priest) on Jul 21, 2011 at 14:33 UTC

    It will work fine for sub parameters. You can provide a list of keys as a second parameter to lock_keys:

    sub whatever { my %params = @_; lock_keys %params, qw/ key1 key2 key3 /; say "Got key1" if $params{key1}; # ok say "Got key2" if $params{key2}; # ok say "Got key3" if $params{keye}; # Oops - BOOM! } whatever key2 => $value2; whatever keyq => $value1; # Hash has key 'keyq' which is not in the ne +w key set

    For example, I use the following for parsing command-line options in my scripts:

    use Getopt::Long qw/:config bundling/; use Hash::Util qw/ lock_keys /; our %OPT; my @OPT_SPEC = qw/ help|h version noact|no-act|dry-run DEBUG output|o= +s /; GetOptions \%OPT, @OPT_SPEC or ($OPT{help} = 1); lock_keys(%OPT, map /^(\w+)/, @OPT_SPEC);

    Update 2: A diligent Anonymous monk actually tested this code (actually executing proposed code - what a concept) and pointed out that the initial lock_keys suggestion is sufficient. Updated the comments in the code above to reflect this.

    Update: Add example where lock_keys is not quite sufficient... One could solve this in a couple ways without changing how whatever is called: Anonymous monk make all this unnecessary

    # Option 1: use Params::Validate # Option 2: sub whatever { my @param_keys = qw/ key1 key2 key3 /; my %params = @_; $params{$_} //= undef for @param_keys; die "Invalid usage" if @param_keys != (keys %params); lock_keys %params; # ... } # Option 3: sub whatever { my %expected_params = map +($_,1), qw/ key1 key2 key3 /; my %params = @_; for (keys %params) { die "whatever: Unexpected named parameter $_" unless exists $e +xpected_params{$_}; } lock_keys %params, keys %expected_params; # ... }

    Good Day,
        Dean

      As you pointed out, it won't catch typos when calling the subroutine. Which is the important case.

      Since there's no reason to use the hash key more than once inside the subroutine, the protecting inside the subroutine is just overhead, adding absolutely nothing at all of value:

      sub whatever { my %params = @_; my $key1 = $params{key1}; my $key2 = $params{key2}; my $key3 = $params{key3}; ... neither %params, nor the key names are needed anymore ... }
      Alternatively, you can stick the key names in variables.

        Note: Updated my previous reply with various proposed solutions.

        Indeed, the initial implementation (lock_keys %params, qw/ key1 key2 key3 /;) is equivalent to your solution there. Though, my reading of the OP was that they wanted to use hashes rather than set a bunch of variables like that and lock_keys offers no less protection than the originally proposed Tie::Hash::Vivify.

        My personal use of lock_keys is restricted to command line option parsing and some cases where it is "easy" to set up on hashes that may be passed around or used a lot (for example, log file parsing as described in The value of declarations). If I were looking for a complete solution for subroutine arguments I would most likely reach for Params::Validate or similar since once you move beyond lock_keys %params, qw/ key1 key2 key3 /;, the added coding effort for proper validation (vs just verifying key names) isn't much.

        Good Day,
            Dean

      whatever keyq => $value1; gives: Hash has key 'keyq' which is not in the new key set at ...

      Seems useful enough.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://915867]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (16)
As of 2014-04-18 15:17 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (469 votes), past polls