Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery

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

by duelafn (Vicar)
on Jul 20, 2011 at 14:45 UTC ( #915668=note: print w/replies, xml ) Need Help??

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

See also Hash::Util which is in perl core since 5.8.0

use Hash::Util qw( lock_keys ); my %hash = (foo => 42, bar => 23); lock_keys(%hash); say $hash{bae}; # Boom! "Attempt to access disallowed key 'bae' in a + restricted hash..."

Good Day,

Replies are listed 'Best First'.
Re^3: Benifits of using hash rather than number of variables?
by JavaFan (Canon) on Jul 21, 2011 at 13:39 UTC
    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;

      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,

        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.
        whatever keyq => $value1; gives: Hash has key 'keyq' which is not in the new key set at ...

        Seems useful enough.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://915668]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (12)
As of 2017-07-26 09:26 GMT
Find Nodes?
    Voting Booth?
    I came, I saw, I ...

    Results (387 votes). Check out past polls.