Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Tied Variables - why?

by samurai (Monk)
on Sep 07, 2002 at 01:03 UTC ( #195812=perlmeditation: print w/replies, xml ) Need Help??

I have been reading my latest version of the Camel Book, and I wonder to myself... what good are tied variables?

Hear me out before anyone gets upset. First... one of people's complaints about perl is that it's far too hard to understand and read. While I don't agree, I think tied hashes add an unnecessary layer of complexity that doesn't make much sense when you already have objects.

Imagine a novice looking at the following two code snippets:

<newbiecommenting>

# tie tie $var, "classXYZ"; $var = 5; print $var; # yields 25... ??? # objects my $var = new Squareable(5); $var->square(); print $var; # oh... yields 25... neato!
</newbiecommenting>

Granted, this is a bit of a juvenile example, but do you see what I'm getting at? How is a novice supposed to be able to discern this type of behavior? In the second example, it's easy to tell what happened. Objects are more self-documenting even without POD.

I know modules like the Ordered Hash Tie module are helpful, but even that could have just been an object.

Perhaps I'm missing something, but I just don't understand Tied variables. Even tied filehandles are probably better just as an object or an extension of FileHandle. You formally declare your behavior instead of hiding it behind the way that perl NORMALLY behaves.

If someone could enlighten me as to some really good uses of tied hashes that make more sense than using a similarly coded object, please do. Perhaps I'm just looking at it wrong.

--
perl: code of the samurai

Replies are listed 'Best First'.
Re: Tied Variables - why?
by erikharrison (Deacon) on Sep 07, 2002 at 02:40 UTC

    First off, let it be pointed out that just because a concept is difficult for a beginner does not rule out it's usefullness or power. Objects are not for beginners either. They seem intuitive in the small but they loose that quite quick, as details about classes and inheritance come into play. It's got great syntax as far as organizing the body of your code, but there are lots of details that make it harder to learn to use. This is one of the great advantages of tie: nice syntax without much of that malarky as far as the user goes.

    Tied variables are can be very useful and very intuitive. For example take a recent node: Unable to save changes using IO::File. Here is a case where the behavior of the object was not clear but Tie::File would have DWIMed perfectly. The general rule for using a tied variable is when Perl's native syntax fits the problem perfectly, but the underlying implementation does not. Why make an object and have to implement functionality that already exists (like sort for example, or keys) when you don't need to add anything? Why reinvent the wheel? In this sense, tie could be seen as perl's way of inheriting from built in types, but in a very clean and easy way.

    And then there are the esoteric uses of tie. Dominus cleverly found a way to extend Memoize's functionality without slowdown or extensive changes to the modules by using tie. This would have been much harder with just objects, not to mention slower, defeating the whole point of having Memoize. Another thought is that, since an object is just a blessed referent, then why not bless a ref to a tied variable? All sorts of nifty magic happens then - for example I am working on a module that would implement Perl 6's accesssor methods syntax in Perl 5. This would not be possible if it weren't for the "weird" and "hard for newbies to understand" features of Perl - source filters, overriding built ins and (you guessed it) tied variables.

    One of the things that I love about Perl is that if the core can do it then you can probably do it to, and in pure Perl no less. Have you ever used a special variable in Perl? Liked 'em? Then the beauties of the tie approach should be clear. Ever wanted to implement your own magic variables? Then you need tie.

    Cheers,
    Erik

    PS - I'm a bit of a tie evangelist, as you may have noticed. Sorry about that. :-)

    Light a man a fire, he's warm for a day. Catch a man on fire, and he's warm for the rest of his life. - Terry Pratchet

Re: Tied Variables - why?
by dws (Chancellor) on Sep 07, 2002 at 02:04 UTC
    I think tied hashes add an unnecessary layer of complexity that doesn't make much sense when you already have objects.

    One benefit of tied objects is that, depending on how the class they're tied to behaves, one can slip them in in place of a scalar type, without most of the code knowing the difference. Aside from the well-known example of tying a hash to a DBM file -- transparently moving a hash from in-memory to on-disk, tying can be incredibly handy for some profiling and debugging work, as when you find yourself in the position of needing to count how many times a value gets read or written.

Re: Tied Variables - why?
by Revelation (Deacon) on Sep 07, 2002 at 04:10 UTC
    According to perltie: The tie() function binds a variable to a class (package) that will provide the implementation for access methods for that variable. Once this magic has been performed, accessing a tied variable automatically triggers method calls in the proper class. The complexity of the class is hidden behind magic methods calls. Basically, tie() is used to make a complex system of functions a simple scalar or hash.

    What this comes down to, and the reason I use perltie often is because tying to a scalar or a hash is functioning as a way to limit the complexity a user has to deal with, and at times a tied value may just seem intuitive.

    A good example in both cases is Apache::Session. The interface to Apache::Session is very simple: tie a hash to the desired class and use the hash as normal. It's much simpler for a user to just modify a hash value, and let Apache::Session do the real work, than it would be otherwise. A hash seems much more intuitive, and simpler to manipulate than an object that may be messed around with, or a user misusing subroutines. There is *no* way for a user to mess up, when using Apache::Session.

    Another example would be lots of data manipulation drivers/modules, such as Tie::File, and DB_File. Hash provide organization for our data, and tied hashes just seem to be perfect for retrieval and insertation of data. There are probably countless other examples, as well, where a tied file just *feels* right, and in perl TM..... means we can do things in our own style, which may very well be tie() :)

    Hope that helps, but if you still don't believe tied variables are any help, I'd advise you to read this article, if you want a more detailed explanation by a better coder.
    Gyan Kapur
    gyan.kapur@rhhllp.com
      Apache::Session is not a good poster child for the use of tied interfaces. There is a constant stream of questions on the mod_perl and Mason mailing lists from people who are having problems becuase of it. They get bitten by scoping problems, can't figure out how to call methods on the tied hash, or have trouble with deep updates (updating something that is not at the top level of the hash, which fails to call the STORE method in Apache::Session). Many of these problems would just go away if Apache::Session didn't have a tied interface.
Re: Tied Variables - why?
by Arien (Pilgrim) on Sep 07, 2002 at 11:34 UTC
    I think tied hashes add an unnecessary layer of complexity that doesn't make much sense when you already have objects. ... You formally declare your behavior instead of hiding it behind the way that perl NORMALLY behaves.

    What behaviour is there to hide when it's the usual behaviour you've come to expect of Perl?

    The key to tied variables is to make them look so much like a regular variable that you forget what is going on underneath. Obviously, you can only get this to work if the behaviour you're trying to implement maps nicely on the normal behaviour of whatever your tieing to.

    Your example shows what happens when there is a impedance mismatch between the behaviour you're implementing and how the variable type you've chosen for your tie normally works in those circumstances. The conflict with the expected behaviour is a result of using the wrong metaphor: you are luring the user into thinking all is normal, when in fact it is not.

    As an example of a module, have a look at Tie::File, which does this (example code snipped):

    Tie::File - Access the lines of a disk file via a Perl array.

    Tie::File represents a regular text file as a Perl array. Each element in the array corresponds to a record in the file. The first line of the file is element 0 of the array; the second line is element 1, and so on.

    The file is not loaded into memory, so this will work even for gigantic files.

    Changes to the array are reflected in the file immediately.

    Lazy people and beginners may now stop reading the manual.

    Because you know how arrays work, you could now very likely start using this module without any problem whatsoever. If you had to use a "similarly coded class" you would still be going over the methods to see how things work in this particular case.

    Now, that is the beauty of using tie.

    — Arien

      So Perl intertwines expectations about behaviour with syntax.

      We then find out that there are times we want something that is a lot like, but not quite, a native Perl data structure. The fact that there is no obvious way to do that is a self-inflicted injury, and magic is the band-aid that Perl applies.

      But users often what behaviour that it a lot like something that Perl does. tie is a wrapper around the magic band-aid to give users a band-aid for that problem.

      But people often want something that is a lot like something that Perl does, but not exactly! Which introduces tied - Perl's way to lift the band-aid and scratch the raw wound left beneath.

      At some point I wonder whether it wouldn't be easier to just not injure ourselves in the first place?

        So Perl intertwines expectations about behaviour with syntax.

        Quick, what does $bar = $foo{bar} mean? What does it do? How do you know, you've just seen syntax?

        Perl lets you tie a behaviour to a particular syntax, because people relate syntax with behaviour. Using the right combination, this makes things easier because you raise the level of abstraction and reuse a familiar conceptual model including its syntax. It makes it appear that there is a special builtin type that eg. knows that you want the lines of a file as an array and lets you work with that array (conceptually and notationaly) just like any other array. How cool is that? :-)

        tied is the way to get past tie's illusion and the only thing you'll find is that you were tricked, but you should have known that all along. That you need tied to remind you just goes to show how effective tie can be in creating the illusion in the first place.

        — Arien

Re: Tied Variables - why?
by shotgunefx (Parson) on Sep 07, 2002 at 09:52 UTC
    To add to these other good examples, take CGI.pm

    Often I'll have to generate a select tag (popup_menu) with different key and values. The way to do this in CGI.pm is by passing a hash. Usually you'll want them sorted by the display value, but hashes are intrinsically unordered.

    What to do?

    Simple
    # Kludge to get options sorted. package MySortHash; use Tie::Hash; use vars qw(@ISA); @ISA = qw( Tie::StdHash ); sub FIRSTKEY { my $self = shift; @{ $self->{VERY_UNLIKELY_HASH_KEY} } = sort {$self->{$a} cmp $self +->{$b} } grep { $_ ne 'VERY_UNLIKELY_HASH_KEY' } keys %{$self}; return shift @{ $self->{VERY_UNLIKELY_HASH_KEY} }; } sub NEXTKEY { my $self = shift; return shift @{ $self->{VERY_UNLIKELY_HASH_K +EY} }; } # later in package main... tie %thash, 'MySortHash' ; # tied hash with sorted keys... print $q->popup_menu(-name=>$p , labels=> \%thash, -values=> [ (keys % +thash) ] );
    Now I could subcass CGI and muck around with popup_menu or I could write yet another CGI module but why when I can coax CGI.pm into DWIM with in 10 lines of code? My favorite uses usually are coaxing some new behavior out of existing code. Paging/Filtering filehandles.. etc.

    -Lee

    "To be civilized is to deny one's nature."
      Good example, but you could cut down further. :-)
      use Tie::IxHash; tie %thash, Tie::IxHash; print $q->popup_menu(-name => $p, labels => \%thash, -values => [ keys + %thash ]);

      Makeshifts last the longest.

        Good point. In CGI scripts, I like to keep the number of modules that need to be loaded down when it makes sense. Especially small things like this but YMMV.

        -Lee

        "To be civilized is to deny one's nature."
Re: Tied Variables - why?
by Anonymous Monk on Sep 07, 2002 at 01:21 UTC
    Hear me out before anyone gets upset. First... one of people's complaints about perl is that it's far too hard to understand and read. While I don't agree, I think tied hashes add an unnecessary layer of complexity that doesn't make much sense when you already have objects

    Get real, I was upset right after seeing the title *grin* but seriously, heard of DB_File? The point behind the tie interface is to have the good old familiar perl data structures, like %Hashes and @Arrays, which do incredibly magical things.

    How is a novice supposed to be able to discern this type of behavior

    The same way an experienced perl programmer is, by reading the pod of the associated module.

    You wanna print scalar <FILEHANDLE>, why would you want to print $FileHandle->readline?

Re: Tied Variables - why?
by perrin (Chancellor) on Sep 07, 2002 at 15:20 UTC
    An anecdote:

    I had written most of a program to generate a big SQL import script when I realized that I actually needed some data I had stored in hashes to retain its order. I could have changed my code to use an array as well as a hash, but instead I just replaced the hashes with Tie::IxHash and everything just worked, with no other code changes. That was beautiful.

    I usually avoid using tied hashes because they are slower than just calling object methods, but in this case it was really handy.

Re: Tied Variables - why?
by boo_radley (Parson) on Sep 07, 2002 at 15:54 UTC

    I think you've stumbled onto one of the reasons why people use tied variables in the first place in your second example :

    # objects my $var = new Squareable(5); $var->square(); print $var; # oh... yields 25... neato!
    the output you'll get here (unless the Squareable author's been exceptionally concerned about creating a default accessor) is something similar to "Squareable=HASH(address)", not 25. print $var would print 25, however, when set up as a tied scalar.

    Tied variables are set up to provide the programmer with a simple way of using accessors and mutators without having to worry about semantics at all.
    I'd use create a tieable class if I were concerned about making a class behave and operate "just like" one of perl's 3 variable types.

    When used correctly, tied variables can reduce the amount of knowledge a programmer needs to have about a given class ("Is squarable's output method ->output(), or ->product(), or ->result() ?" vs. "print $foo"). There's an excellent example in Damian Conway's OOP book that uses math classes : It's not as clear to have

    $int->add(4); $int->divide(12); print $i->value();
    as it would be to have
    $i=$i+4; $i=$i/12; print $i;
    (I can't remember offhand if tied variables allow you to use += and friends right now, or if that's just overloading, so I'll play it basic...)

    As with anything, if tied variables are not a common part of your toolbox, comment their uses through your code to remind you and your maintainers of what's going on.

Re: Tied Variables - why?
by sauoq (Abbot) on Sep 07, 2002 at 23:51 UTC

    This is just another case of there being more than one way to do it. No matter what you have to do, you could find a way to do it without tie. But since tie is there, you can use it if you want, you think it makes sense, or it saves you some work.

    One might also say, "we already have a for loop which would allow us to iterate a variable over an array's indices," and then ask, "what good is a foreach loop?"

    -sauoq
    "My two cents aren't worth a dime.";
    

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://195812]
Approved by PodMaster
Front-paged by rinceWind
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others wandering the Monastery: (5)
As of 2021-04-19 22:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?