http://qs1969.pair.com?node_id=500598


in reply to Using references as hash keys

Ordinarily, this is fine. However, if we only care about the values a reference contains and not whether or not it's the same reference, we're stuck. I'd like to be able to pass the constructor a coderef which will determine equality of references beyond simply comparing their addresses.

Well, if you're using Perl's native hashes behind the scenes then you could just use Storable... maybe something like:

use Storable; sub identity_of { my $thing = shift; local $Storable::canonical = 1; return ref $thing ? Storable::freeze( $thing ) : $thing; }; my $array = Array::AsHash->new({ array => [ [1,2,3] => 'Ovid' ], hash_on => \&identity_of, });

If you want to go hard-core implement your own hashing behind the scenes and pass hash and equality functions :-)

For those wondering why I want to do this, I don't need this myself (yet), but I'm creating a flexible general purpose tool for folks and I'd like to give them the ability to override behavior as needed.

What was it you said recently about YAGNI?

Replies are listed 'Best First'.
Re^2: Using references as hash keys
by Tanktalus (Canon) on Oct 16, 2005 at 18:03 UTC

    Preamble: I'm not convinced of XP. And the OP design makes me shake my head in wonder as to why one would want this behaviour.

    That said, I don't see this as YAGNI. YAGNI simply cannot apply to public APIs. For example, Tim Bunce may not need all the APIs provided by DBI, but users of DBI may, among all of them, need those APIs. Different APIs that do things the same way, but return their results differently (selectall_arrayref vs selectall_hashref vs ...) aren't "needed", but sure as heck provide significant amounts of syntactic sugar that simplify oft-used paradigms while leaving flexibility to do things slightly differently if you feel/have the need.

      And the OP design makes me shake my head in wonder as to why one would want this behaviour.

      I can think of some times in the past when something like this would have been useful to me. Having non-primitive ordered pairs can sometimes be useful.

      YAGNI simply cannot apply to public APIs. For example, Tim Bunce may not need all the APIs provided by DBI, but users of DBI may, among all of them, need those APIs. Different APIs that do things the same way, but return their results differently (selectall_arrayref vs selectall_hashref vs ...) aren't "needed"

      I think we're using different definitions of YAGNI. YAGNI isn't about having minimal interfaces. It's about avoiding the expense and potential error involved in writing code before a need for that code has been demonstrated.

        No, I think we're using the same definition. I'm just pointing out that the developer of "it" may not be the user of "it" especially as it pertains to APIs.

        I understand YAGNI's usefulness for in-house software, or internal functions inside software that will escape to users' machines. Only write what you need, when you need it.

        The problem is that if Tim Bunce never needed selectall_hashref, who would write it? Would each user of the DBI that needed it then write it, and we would end up with about two dozen different selectall_hashref's, with a half-dozen different sets of parameters, some of which only work with Oracle, some only with MySQL, some with DB2, ...? Or, if Tim sees the usefulness of this function (to others, in the future), he can easily put it into the official DBI, and save hundreds of developers hours of time each?

        Similarly in my own code - we put in a bunch of functionality that we won't use. But it allows our customers to plug in (using Java, C, perl, or even shell) and do things. We can't be sure that all of the functionality that we build in will be useful. In fact, I'm pretty sure that some of it is useless. Just that I'm not entirely sure which parts that is ;-) So we build it all, and hope they come. Er, we build it all and let each user decide which part(s), if any, they need. Maybe we'll use it, too, in the next version. But for now, we don't. Yet, as a public API which we think is large enough for everyone to do what they need to do, we have to build it now, even if parts of it will never be needed. If we waited to find out if someone needed a particular piece of function before writing it, well, our next release is slated for a year from the release of the current version. And, no, this cannot be fixed in between.