#2345 Does Fantom have a Set class?

mike Fri 12 Sep 2014

Does fantom have a Set class, a.k.a. wrapper for java.util.HashSet? I can't find it...

SlimerDude Fri 12 Sep 2014

Not really...

...but you can use List.unique() to create a set of unique list items.

brian Fri 12 Sep 2014

No we don't have a Set class and it sucks. Right now you have to use a Map (typically I just map values as both the key and value). Its a very poor man's Set.

The main reason I haven't added a Set class is because of the generics issue. We could make another special case for generics like we did List, Map, and Func - and I'm not sure that wouldn't be that bad a trade-off. But I really think the better design would be use whatever user defined generics mechanism we create. Hence the delay in a proper Set class

SlimerDude Fri 12 Sep 2014

An ugly alternative could be to use the keys in a Map:

uglySet := Str:Obj?[:]
uglySet.add("key", null)
uglySet.add("key", null)  // throws ArgErr

Or use Map.set(...) for a safe alternative:

uglySet := Str:Obj?[:]
uglySet.set("key", null)
uglySet.set("key", null)  // allowed

But Map keys and List.unique() all use equality (==) for comparison, to use identity (===) you'd have to roll your own List wrapper to check:

class Set {
  Obj?[] list := [,]

  This add(Obj val, Bool checked := true) {
    if (list.indexSame(val) != null)
      return checked ? throw ArgErr("Dup") : this
    list.add(val)
    return this
  }
}

I know Brian has mentioned in the past he'd like to add Set functionality to Fantom. Maybe it could be set via an it-block in the List ctor like ordered or caseInsensitive is in Map?

set1 := [,] { it.setEquality=true }

set2 := [,] { it.setIdentity=true }

I've found that in real usage, although most of my Lists are actually Sets (as in they don't or shouldn't have duplicates) because I usually manipulate the list as whole and don't add an item here and an item there - I rarely have to enforce the Set construct.

maaartinus Sun 14 Sep 2014

No we don't have a Set class and it sucks. Right now you have to use a Map (typically I just map values as both the key and value). Its a very poor man's Set.

This may backfire badly in case of java HashMap. Look how it's entry hashCode is defined.

Login or Signup to reply.