5 ms·
There is a slight difference between the two. With a map[†]bool, you can do something like: if myset[thing] { ... } With a map[T]struct(), you end up with: i
by randomswede 5y ago
There is a slight difference between the two. With a map[†]bool, you can do something like:
if myset[thing] { ... }
With a map[T]struct(), you end up with:
if _, ok := myset[thing]; ok { ... }
Sometimes, the saving in space is TOTALLY worth the extra verbosity. Sometimes, the slight clarity from "non-existent keys return the zero value" wins.
- morelisp 5y agoWell, now there's no excuse for not having `myset.Contains(thing)` (though there really wasn't before either) which is even clearer.
- thegeekpirate 5y agoYou've also opened yourself up to bugs by allowing the map values to be "false". Using a "set's" value in an if statement doesn't make sense either, compared to if _, exists := something[item]; exists { ... } which is explicit regarding what's actually going on. As Rob said, "Clear is better than clever." https://www.youtube.com/watch?v=PAAkCSZUG1c&t=875s https://www.youtube.com/watch?v=PAAkCSZUG1c&t=875s I also don't want to be hunting down whoever creates a map[T]bool and doesn't leave a comment explaining it's a set ;) Hopefully we won't have to worry about it for much longer regardless, since I imagine we'll be using proper sets (with methods) some point in the near future.
- randomswede 5y agoI would say that "exists in the set" is determined only and exactly by "mySet[thing]" returning true, not that there happens to be a key in the map. But, that's one of those "requires extensive documentation" (and ideally, wrapping in a custom type and provide methods for checking and manipulating the set(s)).
- yencabulator 5y agoNow every range over your set is likely to be a bug. `map[T]bool` is simply a bad design to use.
- randomswede 5y agoHow? Why? If you use the map[T]bool, you obviously need to pay attention to the bool value, even in a range. Whereas in map[T]struct{} you don't need to pay attention to the values. In either way, even with that type of data type underlying a set, I would (probably) provide a functional API to interact with it.
- yencabulator 5y agom["x"] = foo() for k := range { // if foo returned false, this is buggy }
- randomswede 5y agoYes, as I said, if you use a map[T]bool, you need to use something like: for k, v := range m { if v { } } But it also allows you to use "if m[key] { ... }". It is literally a trade-off for what convenience you want. And in both cases, you should (probably) wrap an abstraction around the raw map.