-
Notifications
You must be signed in to change notification settings - Fork 33
Conversation
@@ -118,6 +118,16 @@ ch2 = chain(1:0, 1:2:5, 0.2:0.1:1.6) | |||
@test eltype(ch2) == typejoin(Int, Float64) | |||
@test collect(ch2) == [1:2:5; 0.2:0.1:1.6] | |||
|
|||
ch3 = chain(1:10,1:10, 1:10) | |||
@test length(ch3) == 30 | |||
@test Base.iteratorsize(ch3) == Base.HasLength() |
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.
iteratorsize
is imported (if available) and otherwise defined in this package, so it shouldn't be prefixed with Base
. (Causing tests to fail.)
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.
looks like I introduced some typo at the last moment just before pushing it (Meth instead of MethodErrod), that was causing the failure
Base.iteratorsize is doing the right job on my machine, i.e. using the method defined in Iterators.jl. Should I still change the test?
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.
It doesn't exist in Base
in Julia v0.4.
https://travis-ci.org/JuliaLang/Iterators.jl/jobs/166702724#L185
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.
ah, I see, sorry, I was looking at 0.5 travis build
I can switch Base.Iteratorsize to Interface.Iteratorsize but we still have a problem with Base.HasLength(). Should I put the whole test inside a
if VERSION >= v"0.5.0-dev+3305"
...
end
?
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.
Yes, I think that sounds good.
the test should be good also on 0.4, thanks @kmsquire for the review. Also, I left the prefix Base., tell me if you want it to be Interators. I can't tell the difference at this point. Do you thinks that this should be merged even if iteratorsize becomes type unstable? julia> c=chain(1:10,1:10)
Iterators.Chain{Tuple{UnitRange{Int64},UnitRange{Int64}}}((1:10,1:10))
julia> @code_warntype Base.iteratorsize(c)
Variables:
#self#::Base.#iteratorsize
x::Iterators.Chain{Tuple{UnitRange{Int64},UnitRange{Int64}}}
Body:
begin
return $(Expr(:invoke, LambdaInfo for iteratorsize(::Type{Iterators.Chain{Tuple{UnitRange{Int64},UnitRange{Int64}}}}), :(Base.iteratorsize), Iterators.Chain{Tuple{UnitRange{Int64},UnitRange{Int64}}}))
end::Union{Base.HasLength,Base.SizeUnknown} |
IMO the way forward is to determine this when constructing |
nice! I'll try to cook something to also preserve julia 0.4 compatibility |
if VERSION >= v"0.5.0-dev+3305" | ||
r = ( x for x in 1:10 if isodd(x)) |
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.
Even though this wouldn't actually run on v0.4, the compiler still attempts to parse it, and unfortunately, this syntax is a parse error on v0.4. 😢
For now, my suggestion is to comment out this test, explaining that it is a parse error on Julia v0.4, and that it should be uncommented when support for v0.4 is dropped.
Current coverage is 94.15% (diff: 100%)@@ master #85 diff @@
==========================================
Files 1 1
Lines 351 359 +8
Methods 0 0
Messages 0 0
Branches 0 0
==========================================
+ Hits 330 338 +8
Misses 21 21
Partials 0 0
|
ok, the tests are passing now, but... on a second thought the problem of type instability has shifted from the function |
I figured a way out of the type instability issue, this should be good now (if tests pass :) |
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.
Base.iteratorsize
should be defined on the iterator type, not the instance.
_chain_is
should return IsInfinite()
as soon as it hits an iterator with IsInfinite()
.
IteratorSize
type import is unused.
There should be more tests for more iteratorsize
iterator combinations.
will do
it does (the line after #fallback)
will remove
I'm kinda impaired here by the 0.4 compatibility requirement (e.g. cannot use generators and test for return type of itersize can be run only on 0.5) |
Feel free to write more 0.5-only tests when necessary. There should be enough available in terms of data structures and other iterators that you shouldn't need generators. |
you're right, sorry, I misread Everything should be fixed now (crossing fingers) |
This is a good plan, and I like the idea of having It has been suggested that This (like #60) is has the property that I personally think that is probably Ok, as But maybe it isn't
Adding that extra type parameter would let you calculate the iteratorsize at construction time -- the constructor is already I note that you have define the iteratorsize recursively. |
Length is O(n), but is we compute it at creation time we have a problem: r = rand(10)
c = chain(r, r)
push!(r, 1.)
length(c) != length(collect(c)) # problem here I think chain should be optimized for small n. It is a good thing also that the constructor chain(x...) enforces btw: length is also implemented for Product (still O(n))
runtime evaluation of iteratorsize, as done with a loop, even at construction time, would cause type instability (see comments above). I fear much more that perfomancewise that recursion. Do you agree? |
I agree. Wouldn't a generated function be type stable?
What do you think? |
I've never |
and here it is the third or fourth life for this pr, now with generated iteratorsize @oxinabox do you know of any downsides of generated functions? All I could find are some, almost creepy, "don't you use them if you don't need them" |
They are spooky pseudo-macros. There are a bunch of things you are not allowed to do with them. There purpose is for writing type generic code, that depends only on the types on the arguments. |
The downside to this is that it will compile a function every time you call All these options will need some empirical measurement. |
only if you chain different types. But that would happen in any case using dispatch I guess.
Yeah, it would be nice to set up the benchmarking framework. I'm sure this is the best approach for runtime speed. I'm not sure about compile speed, though it may be not that relevant. |
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.
Thanks for the coverage! I think I'm alright with this conceptually for now if it doesn't kill benchmarks.
|
||
c = chain(ch1, ch2, ch3) | ||
@test length(c) == length(ch1) + length(ch2) + length(ch3) | ||
#@test collect(c) == [ch1; ch2; ch3] # why doesn't work? |
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.
Remove this commented-out line
@@ -106,7 +109,6 @@ end | |||
|
|||
# chain | |||
# ----- | |||
|
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.
This was a nice blank line.
using Iterators, Base.Test | ||
|
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.
Bring back this whitespace.
@@ -1,5 +1,8 @@ | |||
include("../src/Iterators.jl") |
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.
Remove this please.
iteratorsize{T<:Chain}(::Type{T}) = SizeUnknown() | ||
if VERSION >= v"0.5.0-dev+3305" | ||
# corner case of empty chain | ||
iteratorsize(c::Chain) = iteratorsize(typeof(c)) |
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.
Remove this; there is already a generic function in Base which does this.
end | ||
|
||
r = countfrom(1) | ||
ch4 = chain(1:10, countfrom(1)) |
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.
Deserves an eltype
test.
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.
done
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.
done
end | ||
|
||
if VERSION >= v"0.5.0-dev+3305" | ||
r = distinct(1:10) |
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.
Use distinct(collect(1:10))
; it's possible someone might make a no-op UnitRange
optimization for distinct
.
why travis is taking so long? it's been like 9 hours |
I'm not sure, but I think there are a finite number of |
Specifically, everything in the |
is something missing for this? |
Adds a length function for chains when they are supposed to have one
Probably this is not the right way to do if, since iteratorsize is type unstable. Does anyone have better ideas?