Naming: map.insert(1, 2) vs. map.set(1, 2)

map.insert(1, 2) overwrites any value already set; why can't we have the name "set", which is shorter and (possibly) more accurate?

It's easier for people coming from other languages like JavaScript.

Naming change for common API like this won't happen in general.

set is not really more accurate than insert. It does not convey that it would insert when key is absent. You have to name something like set_or_insert if you want to be "more accurate".

Plus, insert is in line with C++ naming, makes it easier for people coming from C++, which is the primary language Rust tries to attract people from.

5 Likes

Except in C++, as I just found out, insert on std::map only inserts if the key was not already present. C++17 did add insert_or_assign. Both return a reference to the value in the map, as well as a boolean for "was the key not present".

In Rust, insert returns the old value as an Option, so if anything, it could be called insert_or_replace, but that would be very verbose for such a commonly needed operation.

5 Likes

"Set" can mean "set a new property" or "set an existing property". It encompasses both cases.

More important, it's more concise. This is very important: why put up with a longer name when a shorter one is accurate?

It's much nicer for newcomers to the language, and makes existing code better.

I see not reason not to add this alias.

As a member of libs-api, I'm pretty sure I wouldn't sign off on this. Adding just a simple alias is not something we've historically done, and IMO, you aren't accounting for the downsides. Having more choices for something like this prompts questions like, "what's the difference between insert and set?" It leads to decision paralysis in my experience.

18 Likes

FWIW, I am pretty certain that a better API design would have been to assert that the value is not present on insert, and call a method with the current semantics replace. In my code, I almost always end up writing

let prev = map.insert(key, value);
assert!(prev.is_none());

Regardless, it's pretty clear that we aren't going to rename/duplicate widely used adequate `std`` names.

Adding a doc alias (Advanced features - The rustdoc book) might make sense perhaps.

6 Likes

It is also visually shorter. Why are we dooming ourselves to the same fate as Java?

Yes, let's at least add a doc alias. How do you do that?

Rust has a verbosity problem. Why are programs written in Rust considerably longer than their counterparts in languages? A good comparison is Java: the core language is sensibly designed, but the vocabulary is unnecessarily verbose. This makes it hard to read.

Let's make the documentation make clear one of them is favored. I agree, it can befuddle the decision-paralysis-inclined unless we break the symmetry for them.

"set" is slightly more ergonomic, and why should we let a language so young lose ergonomics for the sake of tradition?

Rust is not young. This suggestion for rename could have been actionable before 1.0, nine years ago. Today, there's basically zero chance of something like this happening, regardless of whether this is a good idea in principle. Rust values stability and avoids gratuitous changes.

Speculating on what the API should have been is perhaps useful --- it can help the next language, or inform patterns and idioms in Rust. Arguing for the change in the stable API in this case is not helpful --- it is abundantly clear that it is not changing.

7 Likes

I just gave you a reason that isn't "for the sake of tradition."

Also, I don't accept your premise that this is a loss in ergonomics. Even if I agreed set was a better name, it would be at best a marginally better name. That doesn't mean it has better "ergonomics."

4 Likes

Well, I came here looking for a reason why it shouldn't be "set", and I didn't find one.

I heard only when the possible marginal improvement isn't enough to justify changing it.

It's too bad Rust is already stuck with decisions like these. Back to Zig.

1 Like

I gave you one reason (mimicking C++), you just ignored it. And you are repeatedly claiming set is more ergonomic, which most people here don't agree with.

Totally unnecessary and unsuitable comparison. Zig is a great language idea, but you seems have the misconception that Rust and Zig currently have same maturity and stability guarantee. Rust 1.0 released almost 10 years ago and is now 1.69. While Zig still haven't reached 1.0 release. Of course you get different feedback when suggesting changes like this.

3 Likes

All this talk of connotations and language stability and nobody has mentioned the clearly superiest UPSERT (all caps mandatory).

3 Likes

"Stability without stagnation" arguably exists or do not exist, but screw that! In Rust you don't have to touch upstream to rename(or even add helpers to) arbitrary public API. This is only 10 lines of code:

trait SetIsInsert<K, V> {
    /// Alias for [HashMap::insert](
    /// https://doc.rust-lang.org/stable/std/collections/struct.HashMap.html#method.insert).
    fn set(&mut self, k: K, v: V) -> Option<V>;
}
impl <K: Eq + PartialEq + Hash, V> SetIsInsert<K, V> for HashMap<K, V> {
    fn set(&mut self, k: K, v: V) -> Option<V> {
        self.insert(k, v)
    }
}

These things can sit in your own crate, and any rapid-prototyping framework's prelude could amass a bunch(which are the only place where the ease of typing matters). We really don't need to go through the trouble of migrating from one name to another.

1 Like

Ooh are we bike shedding maps?

Well, obviously, set() would return the contents of the map as a set, so HashMap<K, V>::set(&self) -> &HashSet<hash_map::Entry<K, V>> (where Entry compares only on the key, of course). I'm sure rewriting maps to be in terms of sets rather than the opposite is a minor change.

Insert should fail if the value is already present, and update should fail if it's not, and set is already taken, so maybe we should look to http and use put, since we already have get. Then, clearly, to avoid confusing people used to http, we would need to add delete as an alias of remove, and add post, since that's the only other http method used. For consistency with http, maps should take a Server type parameter that configures what post does to an item.


Sorry if this is a bit saucy! But hopefully the point is made that consistency was a lost cause long before Rust 1.0. Probably around the time the Vikings invaded England is my guess...

7 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.