-
Notifications
You must be signed in to change notification settings - Fork 9
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
WIP Remove dependency on inference #7
Open
davidanthoff
wants to merge
8
commits into
master
Choose a base branch
from
remove-typeinference-reliance
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
2634029
Remove map dependency on inference
davidanthoff 4dc801a
Merge branch 'master' into remove-typeinference-reliance
davidanthoff 18d7a0a
Make EnumerableIterable pass iteratoreltype through
davidanthoff e24426a
Remove debug code
davidanthoff 38d08b4
Add ElUnknown version of filter
davidanthoff 4c86b9e
Add tests for filter
davidanthoff 6100fbd
Make drop iteratoreltype agnostic
davidanthoff da6147a
Make take iteratoreltype agnostic
davidanthoff File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,37 +1,84 @@ | ||
struct EnumerableMap{T, S, Q<:Function} <: Enumerable | ||
# This is the HasEltype() version | ||
|
||
struct EnumerableMapHasEltype{T, S, Q<:Function} <: Enumerable | ||
source::S | ||
f::Q | ||
end | ||
|
||
Base.iteratorsize(::Type{EnumerableMap{T,S,Q}}) where {T,S,Q} = Base.iteratorsize(S) in (Base.HasLength(), Base.HasShape()) ? Base.HasLength() : Base.iteratorsize(S) | ||
Base.iteratorsize(::Type{EnumerableMapHasEltype{T,S,Q}}) where {T,S,Q} = Base.iteratorsize(S) in (Base.HasLength(), Base.HasShape()) ? Base.HasLength() : Base.iteratorsize(S) | ||
|
||
Base.eltype(iter::EnumerableMap{T,S,Q}) where {T,S,Q} = T | ||
Base.eltype(iter::Type{EnumerableMapHasEltype{T,S,Q}}) where {T,S,Q} = T | ||
|
||
Base.eltype(iter::Type{EnumerableMap{T,S,Q}}) where {T,S,Q} = T | ||
Base.length(iter::EnumerableMapHasEltype{T,S,Q}) where {T,S,Q} = length(iter.source) | ||
|
||
Base.length(iter::EnumerableMap{T,S,Q}) where {T,S,Q} = length(iter.source) | ||
function Base.start(iter::EnumerableMapHasEltype{T,S,Q}) where {T,S,Q} | ||
s = start(iter.source) | ||
return s | ||
end | ||
|
||
function map(source::Enumerable, f::Function, f_expr::Expr) | ||
TS = eltype(source) | ||
T = Base._return_type(f, Tuple{TS,}) | ||
S = typeof(source) | ||
Q = typeof(f) | ||
return EnumerableMap{T,S,Q}(source, f) | ||
function Base.next(iter::EnumerableMapHasEltype{T,S,Q}, s) where {T,S,Q} | ||
x = next(iter.source, s) | ||
v = x[1] | ||
s_new = x[2] | ||
v_new = iter.f(v)::T | ||
return v_new, s_new | ||
end | ||
|
||
function Base.start(iter::EnumerableMap{T,S,Q}) where {T,S,Q} | ||
function Base.done(iter::EnumerableMapHasEltype{T,S,Q}, state) where {T,S,Q} | ||
return done(iter.source, state) | ||
end | ||
|
||
# This is the EltypeUnknown() version | ||
|
||
struct EnumerableMapEltypeUnknown{S, Q<:Function} <: Enumerable | ||
source::S | ||
f::Q | ||
end | ||
|
||
Base.iteratorsize(::Type{EnumerableMapEltypeUnknown{S,Q}}) where {S,Q} = Base.iteratorsize(S) in (Base.HasLength(), Base.HasShape()) ? Base.HasLength() : Base.iteratorsize(S) | ||
|
||
Base.iteratoreltype(::Type{EnumerableMapEltypeUnknown{S,Q}}) where {S,Q} = Base.EltypeUnknown() | ||
|
||
Base.length(iter::EnumerableMapEltypeUnknown) = length(iter.source) | ||
|
||
function Base.start(iter::EnumerableMapEltypeUnknown) | ||
s = start(iter.source) | ||
return s | ||
end | ||
|
||
function Base.next(iter::EnumerableMap{T,S,Q}, s) where {T,S,Q} | ||
function Base.next(iter::EnumerableMapEltypeUnknown, s) | ||
x = next(iter.source, s) | ||
v = x[1] | ||
s_new = x[2] | ||
v_new = iter.f(v)::T | ||
v_new = iter.f(v) | ||
return v_new, s_new | ||
end | ||
|
||
function Base.done(iter::EnumerableMap{T,S,Q}, state) where {T,S,Q} | ||
function Base.done(iter::EnumerableMapEltypeUnknown, state) | ||
return done(iter.source, state) | ||
end | ||
|
||
# Implementation of the query operator | ||
|
||
function _map(source::Enumerable, f::Function, f_expr::Expr, ::Base.EltypeUnknown) | ||
S = typeof(source) | ||
Q = typeof(f) | ||
return EnumerableMapEltypeUnknown{S,Q}(source, f) | ||
end | ||
|
||
function _map(source::Enumerable, f::Function, f_expr::Expr, ::Base.HasEltype) | ||
TS = eltype(source) | ||
T = Base._return_type(f, Tuple{TS,}) | ||
if isleaftype(T) | ||
S = typeof(source) | ||
Q = typeof(f) | ||
return EnumerableMapHasEltype{T,S,Q}(source, f) | ||
else | ||
_map(source, f, f_expr, Base.EltypeUnknown()) | ||
end | ||
end | ||
|
||
function map(source::T, f::Function, f_expr::Expr) where {T<:Enumerable} | ||
return _map(source, f, f_expr, Base.iteratoreltype(T)) | ||
end | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,34 @@ | ||
struct EnumerableTake{T,S} <: Enumerable | ||
struct EnumerableTake{S} <: Enumerable | ||
source::S | ||
n::Int | ||
end | ||
|
||
function take(source::Enumerable, n::Integer) | ||
T = eltype(source) | ||
S = typeof(source) | ||
return EnumerableTake{T,S}(source, Int(n)) | ||
return EnumerableTake{S}(source, Int(n)) | ||
end | ||
|
||
Base.iteratorsize(::Type{EnumerableTake{T,S}}) where {T,S} = Base.iteratorsize(S) in (Base.HasLength(), Base.HasShape()) ? Base.HasLength() : Base.SizeUnknown() | ||
Base.iteratorsize(::Type{EnumerableTake{S}}) where {S} = Base.iteratorsize(S) in (Base.HasLength(), Base.HasShape()) ? Base.HasLength() : Base.SizeUnknown() | ||
|
||
Base.eltype(iter::EnumerableTake{T,S}) where {T,S} = T | ||
Base.iteratoreltype(::Type{EnumerableTake{S}}) where {S} = Base.iteratoreltype(S) | ||
|
||
Base.eltype(::Type{EnumerableTake{T,S}}) where {T,S} = T | ||
Base.eltype(::Type{EnumerableTake{S}}) where {S} = eltype(S) | ||
|
||
Base.length(iter::EnumerableTake{T,S}) where {T,S} = min(length(iter.source),iter.n) | ||
Base.length(iter::EnumerableTake{S}) where {S} = min(length(iter.source),iter.n) | ||
|
||
function Base.start(iter::EnumerableTake{T,S}) where {T,S} | ||
function Base.start(iter::EnumerableTake{S}) where {S} | ||
return iter.n, start(iter.source) | ||
end | ||
|
||
function Base.next(iter::EnumerableTake{T,S}, s) where {T,S} | ||
function Base.next(iter::EnumerableTake{S}, s) where {S} | ||
n, source_state = s | ||
x = next(iter.source, source_state) | ||
v = x[1] | ||
source_new = x[2] | ||
return v, (n-1, source_new) | ||
end | ||
|
||
function Base.done(iter::EnumerableTake{T,S}, state) where {T,S} | ||
function Base.done(iter::EnumerableTake{S}, state) where {S} | ||
n, source_state = state | ||
return n<=0 || done(iter.source, source_state) | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,34 @@ | ||
struct EnumerableIterable{T,S} <: Enumerable | ||
struct EnumerableIterable{S} <: Enumerable | ||
source::S | ||
end | ||
|
||
function query(source) | ||
IteratorInterfaceExtensions.isiterable(source) || error() | ||
typed_source = IteratorInterfaceExtensions.getiterator(source) | ||
T = eltype(typed_source) | ||
S = typeof(typed_source) | ||
|
||
source_enumerable = EnumerableIterable{T,S}(typed_source) | ||
source_enumerable = EnumerableIterable{S}(typed_source) | ||
|
||
return source_enumerable | ||
end | ||
|
||
Base.iteratorsize(::Type{EnumerableIterable{T,S}}) where {T,S} = Base.iteratorsize(S) == Base.HasShape() ? Base.HasLength() : Base.iteratorsize(S) | ||
Base.iteratorsize(::Type{EnumerableIterable{S}}) where {S} = Base.iteratorsize(S) == Base.HasShape() ? Base.HasLength() : Base.iteratorsize(S) | ||
|
||
Base.eltype(iter::EnumerableIterable{T,S}) where {T,S} = T | ||
Base.iteratoreltype(::Type{EnumerableIterable{S}}) where {S} = Base.iteratoreltype(S) | ||
|
||
Base.eltype(iter::Type{EnumerableIterable{T,S}}) where {T,S} = T | ||
Base.eltype(::Type{EnumerableIterable{S}}) where {S} = eltype(S) | ||
|
||
Base.length(iter::EnumerableIterable{T,S}) where {T,S} = length(iter.source) | ||
Base.length(iter::EnumerableIterable{S}) where {S} = length(iter.source) | ||
|
||
function Base.start(iter::EnumerableIterable{T,S}) where {T,S} | ||
function Base.start(iter::EnumerableIterable{S}) where {S} | ||
return start(iter.source) | ||
end | ||
|
||
@inline function Base.next(iter::EnumerableIterable{T,S}, state) where {T,S} | ||
@inline function Base.next(iter::EnumerableIterable{S}, state) where {S} | ||
return next(iter.source, state) | ||
end | ||
|
||
function Base.done(iter::EnumerableIterable{T,S}, state) where {T,S} | ||
function Base.done(iter::EnumerableIterable{S}, state) where {S} | ||
return done(iter.source, state) | ||
end | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
using QueryOperators | ||
using Base.Test | ||
|
||
@testset "filter" begin | ||
|
||
X = [1,2,3,4] | ||
|
||
# Test with eltype known | ||
|
||
a = QueryOperators.@filter(QueryOperators.query(X), i->i%2==0) | ||
aa = collect(a) | ||
|
||
@test Base.iteratoreltype(typeof(a))==Base.HasEltype() | ||
@test Base.iteratorsize(typeof(a)) == Base.SizeUnknown() | ||
@test aa == [2,4] | ||
|
||
# Test with eltype unknown | ||
|
||
b = QueryOperators.@filter(QueryOperators.query(i for i in X), i->i%2==0) | ||
bb = collect(b) | ||
|
||
@test Base.iteratoreltype(typeof(b))==Base.EltypeUnknown() | ||
@test Base.iteratorsize(typeof(b)) == Base.SizeUnknown() | ||
@test bb == [2,4] | ||
@test eltype(bb) == Int | ||
|
||
end |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 still relying on inference though? I think to really avoid Inference, we should mirror the implementation of collect on Generators and how the new Broadcast will 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.
The strategy here is to use the information from inference if it gives us a concrete type, otherwise not use that information. I think that is the same strategy that Broadcast is using now? As far as I understand it, that would be an ok use of inference.
The question though is whether it actually buys us anything, or whether we could just never use it. At least for a intermediate period it would help with moving things over: it will take a while to change all the sinks to accept iterators that have the
EltypeUnknown()
trait, and until that is done this implementation here would still return things withHasEltype()
in all cases where it does so today.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.
FWIW, I don't think the question is whether the inferred type is concrete or not. It's rather that the user-visible behavior should be the same whether or not inference gives you a precise type or
Any
.