Do you know where your variables are? | |
PerlMonks |
"Is it a hashref" vs "Can I use it like a hashref?"by blokhead (Monsignor) |
on Jan 19, 2004 at 22:57 UTC ( [id://322466]=perlmeditation: print w/replies, xml ) | Need Help?? |
I was playing around the other day, seeing how I could make some objects play nicer with HTML::Template. I didn't want to just use blessed hashrefs as the object implementation, because I didn't want all the private data visible to H::T. My idea was to use blessed arrayrefs, but overload %{} so H::T could use them as hashrefs. This way, I could still control which keys were visible.
I passed some of these objects into H::T but it didn't work, failing with Single reference arg to param() must be a hash-ref! You gave me a Foo. Dang! I looked in the code and saw that it uses UNIVERSAL::isa to check when it expects a data structure to be a hashref: Well, this is a bummer, I thought. UNIVERSAL::isa (among its other shortcomings for determining the type of a reference) doesn't take overloading into account. I finally had to declare an empty package HASH and put it in @Foo::ISA to get the objects to work cleanly with H::T. Yuck. Not a very elegant solution at all. It dawned on me that asking "is this thing really a hashref?" seems like poor coding -- we are demanding to know something about the implementation of an object. Instead, we should only need to ask things about the object's interface, like "can I use this thing like a hashref?" After thinking about it, I would guess that 90% of the time someone asks that first question, their intent would be better captured by asking the second question. Hopefully the example above with HTML::Template illustrates this. An easy way to check for hash-deref-ability would be to try eval { %{$thing} } and check for failure in $@. But if $thing is overloaded for %{}, this operation could potentially have side-effects for $thing. It would be better to have a way that doesn't introduce possible Heisenberg problems. This is what I came up with, using utility functions from Scalar::Util and overload: It handles overloaded cases correctly, and is not fooled by the same silly cases (ie, bless [] => "HASH") that ref and UNIVERSAL::isa are. I wonder if this function should be included in Scalar::Util (or put in a separate module somewhere), I may email the maintainer to get his opinion. In any case, it would sure be nice for modules like HTML::Template to check for hash-deref-ability instead of checking the true reference type, so we can all use objects with hash-dereferencing overloaded. What are your thoughts? blokhead
Back to
Meditations
|
|