I work a lot with complex data structures. When I need to access a value at some depth nested keys which not guaranteed to exist, I have to write,
sub somefunc {
my($self, $context) = @_;
return 1 # assumed just OK, but no further processing
unless $self->{config}{key1} &&
$self->{config}{key1}{context} &&
$self->{config}{key1}{context}{$context} &&
$self->{config}{key1}{context}{$context}{form};
my $form = $self->{config}{key1}{context}{$context}{form};
# I can work with $form
...
}
in order to avoid autovivification. But I'm getting tired to do that in all over the file, for every Perl file I work on, with distinct CDSes. Once I thought that I might need to restructure my data, but it wasn't possible to do so and it's still not possilbe to restructure now. So I come up with this little tool after doing some searching with
Super Search and
CPAN without satisfying result.
sub is_hash {
my($hash, @keys) = @_;
return unless defined $hash && ref($hash) eq 'HASH';
return $hash unless @keys;
my $yes;
for (@keys) {
$yes = undef,
last unless ref $hash eq 'HASH' && %{ $hash };
$yes = undef,
last unless exists $hash->{$_} &&
defined $hash->{$_};
$yes = 1;
$hash = $hash->{$_};
}
return $yes ? $hash : $yes;
}
Now I can write,
return 1
unless my $form = is_hash($self->{config}, 'key1', 'context', $conte
+xt, 'form');
It's enough for my needs now. It can be extended further to also allow array references in the middle of the chain,
$somedata, $key1, $key2, $idx3, $key4 ....;
Or, to let us specify certain ref type (including non-ref) we want so it terminates if the ref type mismatches,
my $wanted = 'CODE';
# if key3 has a value but not a CODE ref, it croaks
my $code = thefunc($somedata, $wanted, 'key1', 'key2', 'key3');
$code->(@someargs);
So, if you were on my shoes, was it worth for you?
Open source softwares? Share and enjoy. Make profit from them if you can. Yet, share and enjoy!