The name `Iterator`

Warning: bikeshed.

We’re a bit inconsistent presently in whether we use Iterator or iter; usually the former at the trait/type level, and the latter at the method level. For example, we have FromIterator, whose sole method is from_iter.

A recently accepted RFC proposes both to keep trait names grammatically simple and consistent with methods whenever possible.

It’s a minor point, but should we consider using Iter/iter across the board? Or Iterator/iterator? Or is today’s mix warranted as a special case?

The main argument for Iterator at the type/trait level is precedent/familiarity from other languages. And on the other hand, you write the method names far more often, so it makes sense to have them be as short as possible. So there is some justification for today’s state of affairs.

1 Like

I’m definitely a fan of the more concise Iter. It’s not easily confused with a different concept, and a very common type encountered.

1 Like

Unclear: are you also suggesting renaming Iterator/DoubledEndedIterator/etc themselves, or just related traits like FromIterator? I like being able to refer to Iterators, not “Iters”. :confused:

Regardless, I’d like to note that FromIterator is already sort of weird in that it’s rarely called directly, but instead called implicitly with collect(). It’s a wash either way in my mind, but my gut says go with FromIter since iter is generally how code talks about iterators today.

Actually, I’d go the other direction and rename Map to Mapper. When you call map, you get a Mapper (an object that maps); when you call filter, you get a Filter (an object that filters), when you call iter (short for iterate) you get an Iterator. This would also remove any confusion between collections::Map and iter::Map.

1 Like

AFAIK, collections::Map is going away, as are the other collections traits.

Mapper just sounds weird, and it’s double the length. I prefer Map and Iter, in the same vein as Vec over Vector and Bitv over Bitvector and bool over boolean and fn over function. The conciseness really cuts down on visual noise, IMO, especially with multi-level type signatures that are common in the iterators API.

Iter is surely tempting in its conciseness.

One argument against I can thought of is potential future introduction of something like Iterable - a thing that can be iterated through. Then pair Iterator/Iterable will probably look more descriptive and less confusing than Iter/Iterable. But that's just speculations.

A question that often arises in my head is why aren't Option and Result named Opt and Res? : )

3 Likes

As I wrote on that thread I think the logical convention would be that Iterator stays Iterator, and Iterable is instead called Iter. Currently methods which return an iterator are called iter(). An iterable trait would abstract this functionality, and presumably have a single method called iter(). It then makes sense to follow the trait-name-follows-method-name convention and also call the trait Iter.

@glaebhoerl That’s a great point; I think the comment on the other thread hadn’t quite sunk in.

  1. I would strongly oppose renaming the method from iter()—anything else is just too long for the amount of use iter gets.
  2. I get the reasoning behind Iterable => Iter, but I don’t think it’s a good idea in the long run. Personally, I would prefer the longer, more explicit trait names, with the shorter function names. You get the benefits of it being self-documenting, because its the only method in that trait, as well as the benefits of the shorter method names.
3 Likes

The method is the short form of iterate, not iterator. I don’t see a problem with using Iter for the trait name. It’s just as easy to understand so it might as well be shorter.

IMO, having a trait named Iter is a bad idea because once we have Iterable there will be multiple things it could stand for.

I also favor longer names for traits/types and shorter names for methods. I think the current approach is warranted. The idea is that the type is the most important part information wise. If that is clear, shorter method names are fine. In fact, they’re a good thing. In my opinion, too much redundancy (Iterator/iterator) leads to unnecessarily verbose and cluttered code (e.g., Java).

1 Like

Java is verbose and cluttered because it stutters and very WET: Foo foo = new Foo(); This has redundant instances of the word “foo”.

Regarding abbreviations, I dislike them because they shorten word length and hence reduce readability instead of reducing conceptual size by way of abstraction. Any editor with a simple word completion plugin (not to mention IDEs, which Rust would eventually have) should suffice to “fix” the problem of “this take too many keystrokes to type”. Instead of using abbreviations which cost us in code readability.

In short: “Iterator” >>>> “Iter”.

@yigal100 it’s more than that—the choice to use longer names (not just whether they’re repeated unnecessarily due to lack of type inference) has a negative impact on readability I think. When you’re trying to read or write an algorithm, you really don’t need to spell out iterator each time when something like it or .iter() suffices for reference. If you need to write these multiple times in the same function or method or if you’re chaining several methods together, the longer names are not adding anything. It’s not about the number of keystrokes.

Longer type names are fine and usually a good thing. Method names shouldn’t need to be longer just to preserve some sort of symmetry though.

@darinmorrison local variables are a separate issue since they are local. The general rule of thumb should be that the smaller the context (scope) of an identifier the shorter it can be. So it is perfectly fine to use (e.g. in c++): for (int i = 0; …) For a local short loop of a few lines. For method/function names however this doesn’t apply since their context is larger. in the same vain, API exposed functions should be more descriptive than local private ones.

If you find yourself repeating the same name over and over again while using some API, it is a code smell that demonstrates bad API design where better abstraction should have been used.

In the context of Rust, I’d argue that we should be extra careful naming methods because types are usually inferred and so the only context for human readability is the method name. For example: let it = something.to_iter(); “it” is abbreviated because it’s local to a small context. Inference hides the descriptive type name “Iterator” and the method is also abbreviated so the readability of this line is harmed. Is “it” an iterator or maybe an Iterable?

Yes but this is not always possible. It depends a lot on the level of granularity of the API and the particular task.

I understand the motivation there but I think it gives a false sense of readability. For example, when I see a method named .some_intuitive_name, I still feel the need to look up the type of the method to ensure that I understand what the code is doing. So once I've gone and done that and I have the type in mind, do I need to see it spelled out in full every single time?

And to the point about IDEs, if we have those and we have local type inference, that means we should be able to hover over methods and get the type, so again what's the value in having longer names?

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