-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
RFC: Define length
methods for various iterators, using Inf
as length for infinite iterators
#11977
Conversation
@@ -134,6 +135,7 @@ end | |||
take(xs, n::Int) = Take(xs, n) | |||
|
|||
eltype(it::Take) = eltype(it.xs) | |||
length(it::Take) = min(length(it.xs), n) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be
length(it::Take) = min(length(it.xs), it.n)
?
Is it weird that |
298204e
to
2369580
Compare
@quinnj Yes, I agree its a bit weird---that's why I made it an RFC---but it does seem to work well for these cases. It would be good to know of possible downsides. |
I'd worry about cases where one might do x = 0
for i = 1:length(itr) # --> creates float range
x += i # --> type instabilities
end Not sure if that's a huge case or even a plausible workflow with some iterators, but just comes to mind. |
Would it work to use |
I think having any sort of length definition for infinite iterators is a potentially very messy area. In the motivating example of |
I agree that there needs to be some solution here, but I'm not sure this is it. |
The I do think this is a better idea than a separate integer infinity, but if we did want to go down that route, we could use |
Note that if length can return some form of infinity, this collect method will have to also be changed. |
IEEE decimal floating point formats also have their own "Inf" and "NaN"s, just to be aware of. |
…for infinite iterators. See JuliaCollections/Iterators.jl#42
2369580
to
a1ce5b0
Compare
@phobon Actually, So it turns out 0.4 can't optimise out |
LOL @ ℵ₀ I think this change kind of makes sense. A good example is zipping a finite iterable with an infinite one, whose length can be computed as the min over the zipped iterables, giving the correct answer naturally. |
I find it kind of a pun to return Inf for a length. On a computer, an
infinite collection has no useful length at all. In fact I think the
distinction between having a finite length and not is so important that it
might merit a type distinction of some kind. At least a trait, ideally a
separate abstract type.
|
I think @JeffBezanson is on the right track there. Having any |
I'd guess it's not worth the hassle of dealing with, but since traits, etc., are on the table for dealing with length properties, I'll bring it up in case someone thinks it's important: Iterators often have a known |
a977e34
to
6914d68
Compare
Okay, I realised another deficiency with this approach: type inference is only run before the branch elimination, so julia can't tell that The only way around this would seem to be make this infinity its own type. So in that vein I've created an The only deficiency that comes to mind is that it is impossible to define a type stable |
As it includes a cardinal number, I feel that this PR now truly deserves the "maths" label. |
-1000 to this. If I tried to ask the length of an infinite thing I'd just like to get an error thrown straight away. Return Inf is just being sneaky with semantics, and this new type so much deeper understanding to reason about. |
I still am not clear why infinite iterators need a In short, it seems to me that returning infinity and throwing a |
Another issue is that seems to be moving towards requiring |
The main purpose of this PR is to draw a distinction between:
The reason is that they act in a very different way: when used in [abs(c - big(pi)) for c in take(convergents(pi),10)] On the other hand the output of |
Interesting example there. But since there's no possibility of an infinite comprehension, you could argue that you are required to call |
I'm not sure I understand: once I apply |
Right, what I was suggesting is that there's no problem as things currently are where |
I really really must insist that |
I'll copy-paste my comment from Iterators.jl here since I think it's actually more relevant to this discussion: I think there should just be two different interfaces: an Is it possible to determine a single type parameter from a typejoin of the parameters in the constructor arguments? |
@phobon Which type would |
@JeffBezanson I disagree that I don't quite see the problem with the
which is presumably what you would want: it certainly beats the current behaviour of I concede that |
In all cases, what you want is to use is not a Your point about infinite iterators vs unknown iterators is well-taken though. Maybe there should only be a type distinction for infinite iterators that would let you define, e.g., |
I also think using
and to not call length if not really needed, for example by writing |
I thought |
Similar to the other issue's example you may (reasonably?) want to do:
|
In addition to "infinity", you may want to have a notion of "indeterminate or unknown" length, i.e. iterators where the number of iterations is not or cannot be known beforehand. For example, you may be modelling the interaction between two threads, or reading characters from a socket, or a data structure where determining the length is as expensive as iterating over it and thus not worthwhile. |
Is the conclusion: we should flesh this out with traits once we have #13222 ? |
Yes I think so; I don't want lengths to be infinite. |
See JuliaCollections/Iterators.jl#42 for some discussion.