> On Sept. 22, 2014, 7:19 p.m., Ben Mahler wrote: > > docs/mesos-c++-style-guide.md, lines 96-99 > > <https://reviews.apache.org/r/25622/diff/3/?file=699636#file699636line96> > > > > Why would the iterator be called `containerizer`? > > > > s/containerizer/iterator/ ? > > Dominic Hamon wrote: > -1 > > naming a variable after a type is never a good idea. in this case, you're > getting a containerizer (iterator) from the container of containerizers so > the name 'containerizer' makes sense. > > Ben Mahler wrote: > Sounds confusing. > > Ben Mahler wrote: > If 'auto' was not used here, would we call this 'containerizer'? In a > loop, this would typically be called `iterator`, no? > > ``` > for (auto iterator = containerizers.begin(); iterator != > containerizers.end(); ++iterator) { > Containerizer* containerizer = *iterator; > } > ``` > > Why do something differently when auto is used? > > If the iterator was being "de-referenced" then `containerizer` makes > sense: > > ``` > Containerizer* containerizer = *(containerizers.begin()); > ``` > > Alexander Rukletsov wrote: > I agree with Dominic: it's more important what is stored in the container > and not how we access it (iterator, reference, etc.). Actually, the example > is taken from our code base, see `src/slave/containerizer/composing.cpp:394` > > Ben Mahler wrote: > Ok, since this example uses `containerizer` as a reference to the > `Containerizer*`, as opposed to an iterator, your points make sense. But in > general I don't think this is a pattern we'll want in our code because of the > masquerading types now hidden with 'auto'. > > Iterators are not as simple as a pointer or reference. What I find > unfortunate is that we wouldn't apply the same naming scheme as soon as we > change the container type, which affects the iterator type: > > ``` > map<string, Containerizer*> containerizers; > auto containerizer = containerizers.begin(); // Wouldn't do this. > ``` > > How about a different example here with .find() as opposed to .begin()? > Take a look at cache.hpp as an example: > > ``` > // Evict the least-recently used element from the cache. > void evict() > { > const typename map::iterator& i = values.find(keys.front()); > CHECK(i != values.end()); > values.erase(i); > keys.pop_front(); > } > ``` > > Here we definitely care about the iterator, as opposed to the value, and > would name 'i' accordingly. > > Alexander Rukletsov wrote: > I see. So you would like to be able to 1) distinguish between iterator > type and element type, and 2) be able to reason about the iterator type > somehow (possible from the variable name). I think, that makes sense. > > Using `auto` hides the actual type, and this can be both good and bad. We > should use it in places where we don't care (or shouldn't care) about the > actual type. Do we care about the container and iterator types when > enumerating all elements? I tend to say no, but you are absolutely right that > iterators of different containers are used in different ways. > > Regarding naming, we can choose something general, like "element" or > "item". It will be clear from the context, what this element is about and > implies neither value nor iterator and can be used for both. > > Benjamin Hindman wrote: > To the best of my knowledge we've (or at least I've) used two different > naming schemes for working with iterators in the code base: > > (1) When doing a 'find' we've named the variable the "thing" we're trying > to actually use, for example: > > auto containerizer = containerizers.find("docker"); > > (2) When doing a 'begin' we've named the variable something that makes it > clear it's an iterator, for example: > > auto it = containerizers.begin(); > auto iterator = containerizers.begin(); > > Why? Because for (1) it's highly likely that you'll want to do things > like: > > containerizer->launch(...); > containerizers.erase(containerizer); > > But not: > > ++containerizer; > > Which can be harder to read, especially when initially declared using > 'auto'. Whereas for (2) it's highly likely that we _will_ want to do: > > ++iterator > > Which when named 'iterator' is easy to understand what you're doing. > > That's my suggestion for suggesting a naming scheme for this guide. > > Alexander Rukletsov wrote: > Makes sense, especially `++containerizer`. To make the example less > confusing, I change it to `.find()`. > > Ben Mahler wrote: > Great, Alexander and I chatted off thread as well to go with an example > of .find(). > > Ben: If your example (1) is calling map::find (vector::find does not > exist), then you're actually getting an iterator to map<K,V>::value_type. > This means you need to do 2 operations that you didn't show above: > > ``` > auto containerizer = containerizers.find("docker"); > > // This doesn't not work! > // containerizer->launch(...); > > // (1) First need to check validity. > if (containerizer != containerizers.end()) { > // (2) Have to use get the mapped type out of the iterator with ->second > containerizer->second->launch(...); > } > ``` > > That's why I think even for (1) it's strange to call it 'containerizer'. > If we were getting an `Option<Containerizer*>` from `hashmap::get` then that > would be a good name. > > Grepping through the code I don't see any cases of your naming scheme in > (1)? FWICT we always call the result of find() an 'iterator', or 'i'. > > Alexander Rukletsov wrote: > Both approaches have their disadvantages. This > > auto containerizer = containerizers.find("docker"); > containerizer->second->launch(...); > > is confusing since it's not a containerizer. This > > auto i = containerizers.find("docker"); > i->second->launch(...); > > is too general, it doesn't say what will be launched. Since we introduce > `auto` we definitely want to mention both the type and its meaning. How about > something like > > auto containerizerIt = containerizers.find("docker"); > containerizerIt->second->launch(...); > > I will update the patch with this proposal. > > Ben Mahler wrote: > We would not expect to use an iterator immediately after calling find: > > ``` > auto i = containerizers.find("docker"); > i->second->launch(...); // Crash if (i == containerizers.end()) !! > ``` > > We would need some kind of check, e.g.: > > ``` > auto i = containerizers.find("docker"); > > if (i == containerizers.end()) { > return Error("Docker not found"); > } > > Containerizer* containerizer = i->second; > containerizer->launch(...); > ``` > > In which case, it doesn't have the disadvantage you mentioned earlier IMO. > > Just as a note, in general we've avoided the need to work with iterators > like this if we have our hashmap type. > > ``` > if (!containerizers.contains("docker")) { > return Error("Docker not found"); > } > > containerizers["docker"]->launch(...); > ``` > > Or: > > ``` > Option<Containerizer*> containerizer = containerizers.get("docker"); > > if (containerizer.isNone()) { > return Error("Docker not found"); > } > > containerizer.get()->launch(...); > > ``` > > We don't have a Map type wrapper but it's been talked about a few times. > Probably a bit much for now. ;) > > Alexander Rukletsov wrote: > I think BenH is against saying > > auto containerizer = containerizers.get("docker"); > > so this won't be an example of using auto. What would you say about my > current suggestion: > > const auto& valueIt = values.find(keys.front()); > > Cody Maloney wrote: > > https://www.youtube.com/watch?v=xnqTKD8uD64&list=UUMlGfpWw-RUdWX_JbLCukXg#t=1703 > - Has good guidelines with justification for very liberal usage of auto.
Sutter is a famous auto-advocate. Here is his post about auto (text version of the video : ) ): http://herbsutter.com/2013/08/12/gotw-94-solution-aaa-style-almost-always-auto/ - Alexander ----------------------------------------------------------- This is an automatically generated e-mail. To reply, visit: https://reviews.apache.org/r/25622/#review54173 ----------------------------------------------------------- On Sept. 26, 2014, 12:32 p.m., Alexander Rukletsov wrote: > > ----------------------------------------------------------- > This is an automatically generated e-mail. To reply, visit: > https://reviews.apache.org/r/25622/ > ----------------------------------------------------------- > > (Updated Sept. 26, 2014, 12:32 p.m.) > > > Review request for mesos, Benjamin Hindman, Ben Mahler, Dominic Hamon, and > Till Toenshoff. > > > Bugs: MESOS-1793 > https://issues.apache.org/jira/browse/MESOS-1793 > > > Repository: mesos-git > > > Description > ------- > > Explicitly prohibit the use of namespace aliases. Give examples of preferable > way of using auto. > > > Diffs > ----- > > docs/mesos-c++-style-guide.md 59a39df > > Diff: https://reviews.apache.org/r/25622/diff/ > > > Testing > ------- > > Documentation change, no `make check` needed. > > > Thanks, > > Alexander Rukletsov > >