Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

Ticket #1271 (closed defect: wontfix)

Opened 16 years ago

Last modified 14 years ago

Make comparison in Slink and Hashmap customizable

Reported by: keinfarbton Assigned to: kris
Priority: major Milestone: 0.99.9
Component: IO Version: 0.99.7 Dominik
Keywords: Cc:

Description

I want to create a IdentityHashMap, which uses 'is' instead of '==' to find the keys.

Looking at the tango.util.container makes me think this is not possible ATM.

Change History

10/05/08 04:05:14 changed by kris

  • status changed from new to assigned.
  • milestone changed from 0.99.8 to 0.99.9.

added Identity support to Slink, but not to HashMap yet. Not sure how to expose that in HashMap?, since it's kinda messy to add yet another template argument.

Ideas?

10/05/08 21:55:36 changed by torhu

I'm sorry if this workaround is too obvious, but here you go. :)

import tango.io.Stdout;
import tango.util.container.HashMap;


struct IdentityProxy(T) {
    static assert(is(T == class));  // allow for arrays too?
    T value;
}

// just a shortcut, really
IdentityProxy!(T) byIdentity(T)(T obj) {
    return IdentityProxy!(T)(obj);
}


class A {
    override int opEquals(Object obj)
    {
        Stdout.formatln("A's opEquals called");  // should not happen
        return 1;
    }
}


void main()
{
    auto map = new HashMap!(IdentityProxy!(A), int);

    A a1 = new A;
    A a2 = new A;
    A a3 = new A;
    map.add(byIdentity(a1), 1);
    map.add(byIdentity(a2), 2);
    
    // or like this:
    alias IdentityProxy!(A) wrapA;
    map.add(wrapA(a3), 3);

    Stdout.formatln("map[a1] = {}", map[byIdentity(a1)]);
    Stdout.formatln("map[a2] = {}", map[byIdentity(a2)]);
    Stdout.formatln("map[a3] = {}", map[wrapA(a3)]);
}

Currently it doesn't work if you try to use it with a subclass of A, but that could be added.

10/05/08 23:55:37 changed by torhu

Well, the struct will work with subclasses, just not the function. Maybe it's better to rename IdentityProxy? to ByIdentity?, and dump the function.

An opAssign(T) and opImplicitCast() (when and if that gets added to D 2.0) could be added too, making it a bit nicer to use.

10/06/08 04:37:23 changed by kris

That is indeed a refreshingly nifty approach, though I would wish for a more transparent mechanism for the general user (not keen on requiring wrappers at that level).

It would seem feasible to create a container method to hide this instead. For example, in addition to the add(T) method, we might create an addIdentity(T) method. Er, or maybe not.

I'm trying to think how a subclass of HashMap could hide this part too, but it would likely need to intercept a lot of methods in order to hide things effectively.

Other suggestions?

10/06/08 15:26:22 changed by schveiguy

What about hiding the template arg under another template? i.e.:

// have to define defaultEquals!(T) and identityEquals!(T)

class HashMap (K,V,alias Hash = Container.hash,alias Reap = Container.reap,
alias Heap = Container.Collect,
alias equalsFunc=defaultEquals!(K)): IContainer!(V)

{
// current impl, use equalsFunc to compare nodes for equality
}

template IdentityHashMap(K,V, alias Hash = Container.hash,
alias Reap = Container.reap,alias Heap = Container.Collect)
{
   alias HashMap!(K, V, Hash, Reap, Heap, identityEquals!(K)) IdentityHashMap;
}

This is what I do in dcollections to define the same underlying implementation for sets and multisets (bags)

-Steve

11/09/09 01:28:34 changed by kris

  • status changed from assigned to closed.
  • resolution set to wontfix.

reopen as necessary