Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add some of Iterators.jl to Base? #10162

Closed
JeffBezanson opened this issue Feb 11, 2015 · 23 comments
Closed

add some of Iterators.jl to Base? #10162

JeffBezanson opened this issue Feb 11, 2015 · 23 comments

Comments

@JeffBezanson
Copy link
Member

Several of the types in the Iterators package are widely useful, plus have very small implementations that perform well. I would say these are: Count, Take, Drop, Cycle, Repeat, and RepeatForever. It would make sense to have these in Base.

Also, iterators are afflicted by a mild case of "lettercase hell". We export both Enumerate and enumerate, etc. I would prefer to minimize the number of exported things that differ only in case. There are a few ways to deal with this:

  1. Remove the lowercase versions entirely, and stick with the "uppercase means lazy" convention.
  2. Rename the uppercase versions to something less appealing like EnumerateIterator so they are less easily confused.
  3. Un-export (and possibly rename as well) the uppercase versions.
@StefanKarpinski
Copy link
Member

Could we rename RepeatForever to Repeat and express the old Repeat as a composition of Take and Repeat?

@JeffBezanson
Copy link
Member Author

Yes, that's a good idea. I expect that to work well, since the definitions for RepeatForever are trivial and therefore should inline beautifully.

@jakebolewski
Copy link
Member

This would be great to have, I like option 2 for consistency.

@ViralBShah
Copy link
Member

I think this is a great idea.

@IainNZ
Copy link
Member

IainNZ commented Feb 12, 2015

👍 to option 2, unappealing names for uppercase

@JeffBezanson
Copy link
Member Author

Just out of curiosity, has anybody actually found it useful to refer to the iterator type names, Enumerate, Zip etc.?

@garborg
Copy link
Contributor

garborg commented Feb 12, 2015

There was a proposal in JuliaCollections/Iterators.jl#19 for capitalization to return iterators and lowercase to collect to vectors. I'm not sure I like it as it would make collecting to other container types forever second class, but it seems less confusing than the current case where filter collects if the iterable is an AbstractArray but returns an iterable otherwise, and map only collects.

@JeffBezanson
Copy link
Member Author

JeffBezanson commented Feb 13, 2015 via email

@garborg
Copy link
Contributor

garborg commented Feb 13, 2015

That sounds good. Is a map (imap, etc.) iterator a candidate for Base now that the set of other basic iterators is more complete?

@JeffBezanson
Copy link
Member Author

It's not past tense, it's a participle.

@StefanKarpinski
Copy link
Member

I'd prefer to just make all of these iterators lazy and get rid of the lowercase versions, but that would imply writing Zip(a,b) which looks weird coming from other languages where zip is standard.

@JeffBezanson
Copy link
Member Author

There's some evidence that it's good to have indirection between what you call and the actual type of iterator constructed. For example repeated(x,n) returns a Take, zip(a,b) returns a Zip2, and zip(a,b,c) returns a Zip.

I would love to get rid of the lower/upper duplication one way or another though.

@iamed2
Copy link
Contributor

iamed2 commented Feb 13, 2015

I don't think uppercase looks too weird. In Python 3 and Julia, you are creating an object. It appears to be established standard practice in Julia that creation of an object is done with an uppercase constructor. I think people using iterators in Julia are prepared to use capital letters here.

In general I think it's more important to be internally consistent then to maximize consistency with other languages. IMO zip is to Zip as array is to Array.

@garborg
Copy link
Contributor

garborg commented Feb 13, 2015

If going the all-uppercase route, would exporting abstract supertypes (e.g.
Zip for Zip2 and ZipN) work for providing indirection?

On Fri, Feb 13, 2015 at 11:45 AM, iamed2 notifications@github.com wrote:

I don't think uppercase looks too weird. In Python 3 and Julia, you are
creating an object. It appears to be established standard practice in Julia
that creation of an object is done with an uppercase constructor. I think
people using iterators in Julia are prepared to use capital letters here.

In general I think it's more important to be internally consistent then to
maximize consistency with other languages. IMO zip is to Zip as array is
to Array.


Reply to this email directly or view it on GitHub
#10162 (comment).

@JeffBezanson
Copy link
Member Author

I think it's difficult to be consistent in this case. It's hard to know which operations "create an object" by the standard of this convention, since almost every operation creates an object in some sense.

Another example is keys(d). Should it be KeyIterator(d), or Keys(d) instead? keys could be considered more of an overloadable function, since different collections may want to returns their keys in different ways, while Zip works for all iterators as-is. But the point is, this kind of thinking is very subtle, making it quite non-obvious whether to uppercase something. When teaching julia, I sometimes feel I'm telling people to uppercase things at random.

@ivarne
Copy link
Member

ivarne commented Feb 14, 2015

I like keys as generic overloadable function. KeyIterator is a type that implements the iterator protocol and relies on implementation details of Dict. If my suggestion in #8432 (comment) to make eachindex a method of keys is accepted, the point for keys as a generic function will be strengthend. DataStructures implement keys for a few types, but seem to just proxy to an internal Dict.

Part of the same argument hold for zip, because we use both Base.Zip2 and Zip for efficiency. I don't like it if Zip(1:6, ['H','e','l','l','o','!']) would return an object of type Zip2 instead of Zip.

For enumerate and repeated the choice is more arbitrary, but I still favor the lower case functions. I don't care about the exact type, but rather that I get a reasonably efficient modification of the iterator. Maybe there is a usecase for a more efficient enumerate(::DArray)?

@JeffBezanson: Just out of curiosity, has anybody actually found it useful to refer to the iterator type names, Enumerate, Zip etc.?

As all types, the capitalized iterator names is used whenever you need to explicitly type an expression. Mostly that will be a function where you use multiple dispatch to do something different with a ::Base.Zip2 object, or a ::KeyIterator. I don't think that should come up often, and have taught about suggesting to unexport all of them, so that we don't have Zip, Enumerate, but Base.Zip2.

@JeffBezanson
Copy link
Member Author

Yes, I think the type returned is often an implementation detail of a generic function. You call keys, and part of its job is to pick what type to return. User code constructs specific types surprisingly rarely. I suspect there are many type names currently exported from Base that should not be.

@StefanKarpinski
Copy link
Member

During interactive usage it's very annoying to do typeof(x) and have that type not be something that is actually available to you. I would be ok with unexporting a bunch of types in Base if we changed the printing of those types to include the Base. prefix so that you can input the result of typeof as is and get the right thing back. Of course, that may result in people writing code that is coupled more tightly with things that are not exported from Base, which is also not good. The current situation, while not minimizing exports very well, does at least have the property that we know that we can't just change the names of types willy nilly since people might be depending on them.

@JeffBezanson
Copy link
Member Author

Independent of anything else, it sounds like a good idea to print Base. for unexported type names.

ivarne added a commit that referenced this issue Feb 18, 2015
@ivarne
Copy link
Member

ivarne commented Feb 18, 2015

Fixed the printing issue in 01a2fc8.

It feels wrong that we have to export lots of type names for no reason but a convention that Base. prefixed types are not for public consumption. Seems like we need some middle ground where we document the type, but don't export it to global namespace.

@jakebolewski
Copy link
Member

Can this be closed?

@JeffBezanson
Copy link
Member Author

I guess so; the lowercase/uppercase debate seems to be at a stalemate.

@jakebolewski
Copy link
Member

If you want to compose more than one iterator, to me it seems more natural that they remain lowercase functions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants