shemp has asked for the wisdom of the Perl Monks concerning the following question:

I was looking for a two way hashing solution, and ran across Tie::Hash::TwoWay - which is almost what i need. The drawback is that it starts misbehaving when the two sets being hashed are not disjoint. Any key operation, such as exists, first checks if the specified key exists in the "primary" hash direction, and if so, returns true. If not, it checks the "secondary" hash (the reverse mapping), and returns whether the key exists there.

I need a solution that allows me to specify that the operation should only look in the direction specified with that call. It would not be too hard to modify TwoWay, but i thought id ask if something similar exists. (i didnt find anything at cpan or here - which in no way means that it isnt there)

Thanks much

Replies are listed 'Best First'.
Re: TwoWay hash modification (two hashes)
by tye (Sage) on Jun 25, 2003 at 18:33 UTC

    You don't want a two-way hash, you want two hashes that are kept in sync:

    my( %one, %two ); Tie::Hash::Complementary->marry( \%one, \%two ); $one{foo} = 'bar'; # Also sets $two{bar}= 'foo' $two{baz} = 'bif'; # Also sets $one{bif}= 'baz' $two{bar} = 'oof'; # Does: $one{oof} = delete $one{foo} $one{oof} = 'baz'; # Dies; $two{baz} can't be both oof and bif
    Now you can go find or write Tie::Hash::Complementary.

    Of course you can't have overlap between the keys with a single two-way hash. It is a single hash. You found a module that does something somewhat like what you want, but also fundamentally different than what you want.

                    - tye
      Tie::Hash::TwoWay does actually store the mapping in two different hashes internally, it just doesnt have any way to specify which direction to operate on, it tries the "primary" direction, and if the key doesnt exist, the operation is tried on the "secondary" direction.

      In any case, at lunch today, i designed a tie that does what i need, i'm about to implement it. I'll post about it, and submit it to CPAN, hopefully by the end of the day!
Re: TwoWay hash modification
by halley (Prior) on Jun 25, 2003 at 17:26 UTC
    I would suggest you just work directly with two hashes. Then you have full direct access to either hash as required, as it appears your problem requires you to distinguish them anyway.
    $name{'555-1212'} = 'Jones'; $phone{'Jones'} = '555-1212';
    I'm leery of modules which offer a bag of one-liner idioms, especially when it limits your control over the underlying native structures. Tie::File is cool as its implementation is non-trivial and subtle. Tie::Hash::TwoWay is not cool for the reason you found: it only works if you accept blanket assumptions.

    --
    [ e d @ h a l l e y . c c ]

      Yeah, unfortunately, many modules are not very robust, in that they dont allow for much flexibility. But what can we expect for free! (we do get plenty).

      I want to have the operations encapsulated, otherwise, i'll need to perform operations on both hashes every time i want to do anything to one of them. So, i think im going to design my own variation, where you can specify in which direction the "key" operation should be dealt with. The interface may look something like:
      tie my %hash, 'Tie::Hash::MyTwoWay'; ... $hash->primary()->delete("foo"); $hash->secondary()->delete("foo");
      Here the 2 deletes perform VERY different operations, in that they delete from different directions.

      By default, an operation will take place on "primary"
      For enhancements, i'll probably add optional aliasing of "primary" and "secondary".
Re: TwoWay hash modification
by shemp (Deacon) on Jun 26, 2003 at 18:26 UTC
    I have written a two way hash thats meets my needs. It behaves more like an object than a tied hash, but in many circumstances, it can be used exactly like a hashref. There is really a class that inherits from the tied hash definition. The class takes care of delegating method calls that are above and beyond standard tieing.

    So check it out on my scratchpad

    The class TieControl should be general enough to handle controlling just about any tied variable in a manner similar to this task.

    I'd really appreciate any comments about this project, it will hopefully end up being my first cpan submission.