Just another Perl shrine | |
PerlMonks |
Best Multidimensional Hash Practices?by DamianKaelGreen (Acolyte) |
on Oct 12, 2009 at 19:27 UTC ( [id://800779]=perlquestion: print w/replies, xml ) | Need Help?? |
DamianKaelGreen has asked for the wisdom of the Perl Monks concerning the following question: Oops, I realize now that I made a fairly major mistake in the way I posed my original question a couple of days ago, and it changes the way you have to look at the problem, So I am starting it over anew. (original question: at Best Hash Practices?) The problem really has to do with multidimensional hashes... Before, I was trying to simplify my more complex example by reducing my multidimensional testcase down to a single dimensional hash and failed to recognize that testing a single dimensional hash does not behave the same way as a multidimensional one does. So now my, question has been rephrased here: Q1: (REPHRASED) How do you avoid having to test the existence of a $hash{key}{combination} before testing the existence of its corresponding value? PREMIS: The Perlish way to test if a scalar has been set is to do something like: and for a single dimensional hash:
But when we try to extend that concept to a multidimensional hash, we begin to have a problem. Ideally the perlish way of testing a value in a hash might be to do something like this:
But the reality is that will not work in a lot of cases because entries for the keys automatically get created in the hash when we just try to test if the value is true. To emphasize what I mean, if that hash is tested, and then we do another test on the supposedly empty hash without including the {not} key, then the if statement will return true. For example:
So to get around the problem we end up having to do something like this instead:
But that's a lot of typing, and typing isn't very perlish. It would really be nice if accessing a multidimensional hash in this manner just returned the value if it exists, but since that's not the case, how can we avoid having to repeat the list of keys twice? I thought about using Hash::Util qw{lock_hash unlock_hash) to lock a hash whenever it is not being modified, but programs carp out in the following situation:
Again, not very perlish. So then I considered "use Readonly::Hash"; and then you can do:
and the program will not die. But that only works as long as you never have to modify the hash. When that time comes you're in trouble. There does not seem to be any way to make the hash modifiable again once it is made Readonly... Maybe perl monks know of a way? Finally, I've concluded that the best way to handle this is to just create a separate subroutine that accepts the keys as input, checks the existence of both the key combination and associated value, and then returns the value. But my question to the monks is this: what really is the best way to handle this situation? I'm sure people encounter this problem all the time, and I can't seem to find any documentation for it anywhere. What should the best practice be? The point is that best methods of handling multidimensional hashes need to be clarified somewhere... ---------------------------------------------------------------------- Years later (2013), I'm returning to say that "no autovivification" seems to be the most elegant and perlish solution to the situation above. I have used it in all my code for the past several years and have not noticed any negative side affects. I have even been recommending to other perl programmers I know, to always include this statement at the top of their code, even if they do not know what autovivification means, or they do not expect to encounter any issues involving autovivification, because using it is the simplest way to avoid running into so many unexpected issues. Hope that helps! ---------------------------------------------------------------------- Years later again (2018), I have returned to add a few additional comments: What the "no autovivification" phrase does for us is this:<\p>
Note that the second print statement is different than the one described in the post above. One quick note about using the Autovivification module though: it can be tricky to install... I have encountered many problems trying to install it on various platforms and networks. One of the most common issues has something to do with the "make test" part of the installation. I have found on a couple of occasions that simply by-passing the test allows the installation to complete successfully, and thus far I have not encountered problems by doing so... So if the following doesn't work: cpan install autovivificationThen try this instead:
Back to
Seekers of Perl Wisdom
|
|