No common trait for Map types?


#1

Hi,

I assume I’m missing something, but why is there no common trait for Map operations (i.e. BTreeMap/HashMap). For example, I would expect to be able to write something like:

use std::collections::Map;

fn remove_unwanted(params: Map<&str, &str>) {
    map.remove("password");
}

fn get_params() {
    let bmap = BTreeMap::new();
    let hmap = HashMap::new();

    // Input magic here

   remove_unwanted(bmap);
   remove_unwanted(hmap);
}

However both BTreeMap and HashMap seem to have ‘remove’ and similar operations implemented directly rather than via a common trait. Is this a deliberate choice, and if so what is the recommended method of handling the above situation?

Thanks,
Steve


#2

Rust’s type system can’t currently express traits that have many of the operations you would expect from a Map trait, particularly iteration. The eclectic crate has some experimental ones: https://crates.io/crates/eclectic


#3

I’ve frequently wondered this myself, and to my best understanding, the reason these don’t exist is rather because they would be so fundamentally important! Such traits would be life-changing if they existed, so the bar is understandably set high.

(In fact, if you peek waaaaaaay back in time you’ll find that traits like these used to exist!)

While I’ve no direct knowledge of the history of these traits, part of the trouble with stuff like that is that they invite a significant amount of hierarchy-building, and nobody can agree on how the pieces should fit together. If they’re too small and general, then they’re almost certainly not useful (Iterator is the exception, not the rule!); if they’re too specific, then it won’t take long for somebody to come along with a type that just barely doesn’t fit in.


When I code in Haskell, there isn’t a day that I don’t curse at their Num trait. This one trait provides all of: the binary (+), (*), and (-) operators, unary negation, abs, signum, and fromInteger (used for pattern matching, an extremely fundamental feature).

It was only in May of last year that Haskell’s standard library finally got an unsigned bigint type (Natural) to go along with the signed bigints (Integer) it has had since the dark ages. Needless to say, negate is defined to throw an exception.

Rust on the other hand did away with its Num trait before 1.0 (I think). No cursing from me. (well, maybe less cursing)


#4

Yes, that question is material for a Rust FAQ :slight_smile: