http://qs321.pair.com?node_id=120259


in reply to Re: passing subroutine arguments directly into a hash
in thread passing subroutine arguments directly into a hash

I have tried a number of approaches to this error checking problem. None of them completely satisfied me. But for the moment here is the one that seems to work best.

What I do is having a function that does destructive manipulation of my arguments:

# Takes a hashref, a key name, and an optional default. # Removes that key from the hash, and returns the value or # the default. Blows up if there is no value or default. sub excise_arg { my $args = shift; my $arg_name = shift; if (exists $args->{$arg_name}) { return delete $args->{$arg_name}; } elsif (@_) { return shift; } else { confess("Missing required argument '$arg_name'"); } }
Call it without a default argument and you have a required key. Put in the default and it is optional. And since it is destructive, it gets rid of the keys and I can use this for a typo check.
# Takes a hashref. Verifies that it is empty sub assert_args_done { my @left = keys %{ $_[0] }; if (@left) { confess("Unexpected arguments '@left' left over"); } }
And now in a function I can do this:
sub some_func { my $args = { @_ }; my $name = excise_arg($args, 'name'); # required my $age = excise_arg($args, 'age', undef); # optional assert_args_done($args); # Rest of the code here. }
And if I want to take an existing function and wrap it in one that can handle some things itself and wraps the rest, it is easy. I just excise a few arguments and then pass the rest through untested. As long as they are tested somewhere, typos get checked.

If anyone has alternate suggestions for how to handle this problem, I am open. This seems to work pretty well, but I have tried several things, and I don't claim that this is perfect.

UPDATE
Thanks Hofmator for catching my obvious typo. That is what I get for typing something up off of the top of my head. That is also why I use strict. :-)