<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""></div><div class="">I thought about why release() seems subtly wrong to me for collections, but not for smart pointers. Specifically, release() puts the focus on giving up ownership, but the in the case of a collection, the most important thing is removal from the collection, where giving up ownership is a detail of the removal. In particular, it doesn't leave a hole, like swap() on spot in the collection with a default-constructed value would, or like release() on a smart does. For this reason, I think move() is also wrong in the collection case).</div><div class=""><br class=""></div><div class="">For similar reasons, having a zero-argument remove() on a smart pointer would read a little weird. Sure, you can think of a smart pointer as a collection of one item, but our actual smart pointers either have clear() or no non-returning removal operation.</div><div class=""><br class=""></div><div class="">Therefore I wonder if consistency between smart pointers and collections is really the most important factor. Smart pointers and collections are different enough that their operations don't have to be named the same.</div><div class=""><br class=""></div><div class="">That said, I do have a proposal that I think is semantically OK for both smart pointers and collections, and also has the correct subject in all cases.</div><div class=""><br class=""></div><div class=""><div class=""><br class=""></div><div class=""><div class=""><font face="Courier" class="">&nbsp; Non-removing | &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</font></div><div class=""><font face="Courier" class="">&nbsp; accessor &nbsp; &nbsp; | remove-only &nbsp; | remove+get &nbsp; &nbsp;</font></div><div class=""><font face="Courier" class="">---------------|---------------|-------------</font></div><div class=""><font face="Courier" class="">&nbsp; &nbsp; get() &nbsp; &nbsp; &nbsp;| &nbsp; &nbsp;erase() &nbsp; &nbsp;| &nbsp;remove() &nbsp;&nbsp;</font></div><div class=""><div class=""><br class=""></div></div></div></div><div class=""><br class=""></div><div class="">This has the additional advantage of somewhat more consistency with std:: containers, which name the plain removal operation erase() rather than remove(). A downside is that anyone used to remove() may call it when erase() would do, possibly resulting in slightly less efficient code.</div><div class=""><br class=""></div><div class="">STL smart pointers have a 0-argument reset for non-returning remove instead, and convention seems to be to use swap() or move() for the returning remove on a smart pointer. So an alternate possibility would be to use the above convention for collections, but make smart pointers have no remove+get operation at all.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">For comparison, here is the status quo:</div><div class=""><br class=""></div><div class=""><font face="Courier" class="">&nbsp; Non-removing | Smart pointer | Smart pointer | Container &nbsp; | Container</font></div><div class=""><font face="Courier" class="">&nbsp; accessor &nbsp; &nbsp; | remove-only &nbsp; | remove+get &nbsp; &nbsp;| remove-only | remove+get</font></div><div class=""><font face="Courier" class="">---------------|---------------|---------------|-------------|-------------</font></div><div class=""><font face="Courier" class="">&nbsp; &nbsp; get() &nbsp; &nbsp; &nbsp;|N/A or clear() | &nbsp;release() &nbsp; &nbsp;| &nbsp;remove() &nbsp; | &nbsp;take()</font></div><div class=""><div class=""><br class=""></div></div><div class=""><br class=""></div><div class=""><br class=""></div><br class=""><div><blockquote type="cite" class=""><div class="">On Sep 6, 2016, at 11:07 AM, Geoffrey Garen &lt;<a href="mailto:ggaren@apple.com" class="">ggaren@apple.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">“take” grinds my gears too — though I’ve gotten used to it, more or less.<div class=""><br class=""></div><div class="">I read&nbsp;“object.verb()” as a command, “verb”, directed at “object” (or sometimes as a question, “verb?”, directed at “object”). I think most APIs are phrased this way. And if I were Antonin Scalia, I would make the originalist argument that Smalltalk originally defined a method in object-oriented programming as a message to a receiver — not a message about a sender.</div><div class=""><div class=""><br class=""></div><div class=""><div class=""><blockquote type="cite" class=""><div class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">In the context of a container, take() sort of makes sense by parallel to get(). Though get() could be interpreted as either what the caller is doing or what the callee is doing.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">In other words, you could say that in the code below, function something gets an item from the collection. In that sense, take() is a parallel construct. Of course, you could instead say that function something asks collection to get an item. That's what makes take() not make sense. But I am not sure release() makes sense either way, for a collection. It conveys letting go of the item but doesn't seem to convey fetching in the sake way get() or take() do. I don't think move() would be right in this context either.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">function something(Collection&amp; collection, Key&amp; key)</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">{</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span class="Apple-tab-span" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: pre; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">        </span><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">doSomething(collection.get(key))</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">}</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""></div></blockquote><div class=""><br class=""></div>Though it is possible to read “get” in this context as “I get from collection”, I think it is more natural to read “get” as a command: “collection, get this for me”. Other access verbs on collections, such as “find”, “add”, and “remove”, establish this pattern.</div><div class=""><br class=""><blockquote type="cite" class=""><div class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Given that explanation, I think a possible direction is to rename the smart pointer release() operation to take(). Many of our smart pointers already have a get(). And the idea of taking the underlying value from a smart pointer kind of makes sense, even though it is caller-perspective.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""></div></blockquote><div class=""><br class=""></div></div>I’ve gotten used to “take", so I won’t call it pure applesauce, but it’s not my preference.</div></div><div class=""><br class=""></div><div class="">My favorite suggestion so far is “move”. The C++ standard helps make this a good word because it introduces as terms of art std::move and “move” constructors. But perhaps it is bad for a function named “move” not to return an rvalue reference. For example, one might object to “std::move(collection.move(key))”. Why the double move?</div><div class=""><br class=""></div><div class="">My second favorite suggestion is “release”. It matches a term of art in std smart pointers and it’s pretty clear.</div><div class=""><br class=""></div><div class="">My third favorite suggestion is “remove”. For collections, “remove” is just plain clearer. But “remove” is worse for non-collection value types like smart pointers because we “move” values in C++ — we do not “remove” them.</div><div class=""><br class=""></div><div class="">There are some good thesaurus words like cede or doff or discharge but they all lack familiarity as terms of art.</div><div class=""><br class=""></div><div class="">Geoff</div></div></div></blockquote></div><br class=""></body></html>