Hi. I think this might be just idle thoughts as interfaces have probably calcified as part of the beta shipping, but I thought I'd report on some experiences I've had recently butting my head against some of the library interfaces (mostly collections). These all fall under "my type doesn't implement copy, and I don't want to have to clone it so much", which ends up being an issue for me in "big data" land.
-
Old news: The
HashMap
methodremove(&Key)
returns aValue
, and drops the key that matched. "No problem", you say, because obviously I have a reference to a key. Annoyingly, I wanted to send that key along, and now I have to clone it. It could have returned(Key, Value)
and I could drop the key or not as needed. This ends up being a pain in "word count" like examples where the keys are strings, and I get shown references to keys that need to be shipped.Gankro mentioned that this was known, but that there was not a lot of motivation behind fixing it (perhaps just me, and I'm not particularly passionate).
-
The
hashmap::Entry
methodor_insert_with(FnOnce()->V)
would be super useful if it showed me what the key was. Unfortunately, I had to move it when I calledentry(Key)
, and now I can't see it any more (without a clone). As best as I can tell, none of theEntry
methods (or methods on their variants) expose a reference to the key. -
There were several positive examples (interactions with Gankro et al) where a few
Vec
methods that would otherwise "drop" their backing memory were able to retain it (I think theDrain
iterator came out of this).
I'm sure I've bumped in to other examples (sorry if this fixates on HashMap), where libraries drop or don't share data they got from me, and I want back!
Move semantics and single ownership are great, but "with great power comes great responsibility". It seems like there are a lot of interfaces that could reveal more (references) and drop less.
Is this a well-understood design principle in languages with linear types? It seems like one might want to make a pass over pretty much all of the interfaces with an eye towards this principle, always exposing a maximally sharing minimally dropping interface, and then perhaps wrapping that in convenience methods (for example, the argument that people expect hashmap.remove(&key)
to return just a value works for me, but it is a bummer to not have the more powerful interface somewhere).
I'm happy to take notes on things that I run into, especially if there is a story for how these notes might be useful (e.g. adding such interfaces would be backwards compatible). It is pretty easy to mock up examples where each of these pain points results in substantial overhead, but it also feels like there should be a good principle behind the interface designs that says "even if we don't know why you would want this back, we can at least give it to you and let you drop it"