My often stated opinion on tie
is that it is a hack for a self-inflicted wound.
The self-inflicted wound is that Perl makes an iron distinction between how you manipulate its native data types (scalars, arrays, hashes, filehandles, etc), and how you address user-created data types. From the syntax you can tell whether you have a native data type or a user-created data type. The hack is that Perl offers a wrapper to create something that looks like a native data type from a user-created data type. The hack has several drawbacks, however:
- It can add bugs. With different releases, the bugs move and overall seem to be getting better. But there remain places where tied objects don't quite do what they should. The reason for this is that tie is implemented by putting if checks in every operation that you might do with a Perl "thing". There are a lot of operations, and it is easy to miss something. Grabbing a random one, you couldn't untie a scalar within a tied FETCH until recently.
- It is not extensible. Well, it is if you are willing to tell people that they have to write tied(%foo)->bar("baz") to get at your extensions. But people tend to balk at that. So in practice tie only really works smoothly if the datatype that you are creating corresponds exactly to a native datatype.
- It is slow. I'm not just talking of the performance penalty for accessing a tied object. I'm also talking of the performance penalty for having every operation with native data types have to stop and check whether you are tied or not. If Perl lost tie, it would speed up most code by a reasonable margin.
This is something that I clearly realized after I learned some Ruby. Unlike Perl, in Ruby everything is an object. Including native datatypes. Which means that the equivalent of tie
doesn't even have to be written in Ruby, it is part of the language! (Well, actually the appropriate mix-ins needed to be written to make it easy to emulate native datatypes. But no core change was needed.) And the equivalent of a tied object lacks all of the drawbacks listed above.
Of course the drawback for the way that Ruby does it is that you cannot syntactically tell what anything is. Therefore Ruby cannot auto-coerce as liberally as Perl, and cannot auto-vivify things.
With all that said, what is my advice on tie? I'd say that people should use tie when Perl's syntactic design choices are getting in your way. If, however, you have reason to offer something that is a Perl datatype + more, then I'd bite the bullet and make it a real object.