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).

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.

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.

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.


  Non-removing |             
  accessor     | remove-only   | remove+get    
---------------|---------------|-------------
    get()      |    erase()    |  remove()   


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.

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.


For comparison, here is the status quo:

  Non-removing | Smart pointer | Smart pointer | Container   | Container
  accessor     | remove-only   | remove+get    | remove-only | remove+get
---------------|---------------|---------------|-------------|-------------
    get()      |N/A or clear() |  release()    |  remove()   |  take()




> On Sep 6, 2016, at 11:07 AM, Geoffrey Garen <gga...@apple.com> wrote:
> 
> “take” grinds my gears too — though I’ve gotten used to it, more or less.
> 
> I read “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.
> 
>> 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.
>> 
>> 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.
>> 
>> function something(Collection& collection, Key& key)
>> {
>>      doSomething(collection.get(key))
>> }
> 
> 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.
> 
>> 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.
> 
> I’ve gotten used to “take", so I won’t call it pure applesauce, but it’s not 
> my preference.
> 
> 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?
> 
> My second favorite suggestion is “release”. It matches a term of art in std 
> smart pointers and it’s pretty clear.
> 
> 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.
> 
> There are some good thesaurus words like cede or doff or discharge but they 
> all lack familiarity as terms of art.
> 
> Geoff

_______________________________________________
webkit-dev mailing list
webkit-dev@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-dev

Reply via email to