Re: When to use Tie
by perrin (Chancellor) on Jan 29, 2004 at 16:13 UTC
|
Don't forget, tie is also slow. It's actually faster to call the FETCH and STORE methods of a tied hash class directly than it is to use a tied hash. | [reply] |
|
|
Well, that's obvious, isn't? It's even faster to execute
the body of a FETCH or STORE directly, instead of calling
the sub. Anything where you remove the red tape from is
going to be faster. Whether it's a good idea remains to be
seen.
Abigail
| [reply] |
|
|
It's actually not obvious to many people, since tie is fairly magical. I have often been met with disbelief when I tell people this.
| [reply] |
Re: When to use Tie
by tilly (Archbishop) on Jan 30, 2004 at 01:31 UTC
|
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. | [reply] [d/l] |
|
|
But tie isn't the only kind of magic there is, and all magic (except overload) is triggered by the same code checks. Most of the variables listed in perlvar use some form of magic (admittedly, a few do so uselessly; for example $^O).
I thought untie within a FETCH used to work and got broken at some point along the way and then fixed. This is an area of valid complaint: magic really isn't well represented in perl's regression tests.
Speaking of pervasive performance penalties, perl has an
"optimization" of not reference counting items on the stack (including parameters in @_ in most cases). To keep things from getting garbage collected while still on the stack, it has tons of special code to mark things that should be kept even with a refcount of 0, and special code when dealing with arrays to check if the array at hand is @_ without refcounts. I've often wondered what the gain or loss would be if that mechanism were ripped out and regular reference counting were used for the stack, but its really to late now; there'd be too much work and too much danger of introducing bugs.
| [reply] |
|
|
My gripe with tie in the OP was more of a issue of theory. I specifically avoided implementation issues (like speed).
To me, tie represents the ultimate in encapsulation. In theory, it is completely transparent after you've called tie (though as you mention, there are places where it's not transparent--these places should be considered bugs). It grates on me to see people treating tied hash lookups as if they were method calls, because you're willfully ignoring the reason for tie's existance. Speed is also a concern, but it would still annoy me even if it wasn't a factor.
A short tangent on Ruby: I haven't learned a lot of this language, but what little I studied teached me a few things. I used to wonder why the Java people were in such a huff over integers not being objects. Why would you want to extend the behavior of an integer? Ruby showed me why: it's so you can call operations directly on the datatype, and thus (as you noted) eliminates the need for tie.
---- I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
-- Schemer
: () { :|:& };:
Note: All code is untested, unless otherwise stated
| [reply] [d/l] [select] |
Re: When to use Tie
by shotgunefx (Parson) on Jan 29, 2004 at 16:19 UTC
|
| [reply] |
|
|
I don't view the Acme:: namespace as a "never use this in a real program" place. Rather, it's more of a "isn't this cute?" place. Making a tied hash that does Google searches (like Tie::Google) strikes me as something cute, but doesn't offer more functionality than Net::Google (which Tie::Google is based on).
There are a few odd Acme:: modules that are both cute and useful in production code. I could imagine a few good uses of Acme::SoftwareUpdate. Acme::Morse::Audible might be useful in a Morse code trainer program.
---- I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
-- Schemer
: () { :|:& };:
Note: All code is untested, unless otherwise stated
| [reply] [d/l] |
|
|
| [reply] |
Re: When to use Tie
by davido (Cardinal) on Jan 29, 2004 at 18:43 UTC
|
If one of the goals of object orientation is to hide complexity, then tied datatypes are the ultimate objects. Though I agree that overuse of tie might confuse code maintainers, I believe it has a place in more instances than the narrow situation your post defines.
Yes, tie can be used to produce ACMI:: type results, it can also be put to many legitimate uses. If all you need is a variable that acts in a special way, why bother with an unwieldy object interface? Tie is simply one more tool in the toolbelt of Perl programming. Use it where it's convenient and where it provides clarity or simplicity to design.
| [reply] |
Re: When to use Tie
by Anonymous Monk on Jan 29, 2004 at 23:46 UTC
|
I consider object orientation to be even more abused;
be it good or bad - it's all about the context and (implied)
expectations. | [reply] |