Skip to content

Commit 333ad95

Browse files
authored
Merge pull request #18839 from JuliaLang/jb/itertools
RFC: add `Base.Iterators` module
2 parents d0914f8 + 7cc22c5 commit 333ad95

24 files changed

+676
-601
lines changed

NEWS.md

+4
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ Library improvements
4949
One way of doing this is by adding `ENV["JULIA_INFO_COLOR"] = :blue` to the `.juliarc.jl` file.
5050
For more information regarding customizing colors in the REPL, see this [manual section]( http://docs.julialang.org/en/latest/manual/interacting-with-julia/#customizing-colors).
5151

52+
* Iteration utilities that wrap iterators and return other iterators (`enumerate`, `zip`, `rest`,
53+
`countfrom`, `take`, `drop`, `cycle`, `repeated`, `product`, `flatten`, `partition`) have been
54+
moved to the module `Base.Iterators` ([#18839]).
55+
5256
Compiler/Runtime improvements
5357
-----------------------------
5458

base/REPLCompletions.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -376,10 +376,10 @@ function bslash_completions(string, pos)
376376
# return possible matches; these cannot be mixed with regular
377377
# Julian completions as only latex / emoji symbols contain the leading \
378378
if startswith(s, "\\:") # emoji
379-
emoji_names = filter(k -> startswith(k, s), keys(emoji_symbols))
379+
emoji_names = Iterators.filter(k -> startswith(k, s), keys(emoji_symbols))
380380
return (true, (sort!(collect(emoji_names)), slashpos:pos, true))
381381
else # latex
382-
latex_names = filter(k -> startswith(k, s), keys(latex_symbols))
382+
latex_names = Iterators.filter(k -> startswith(k, s), keys(latex_symbols))
383383
return (true, (sort!(collect(latex_names)), slashpos:pos, true))
384384
end
385385
end

base/asyncmap.jl

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# This file is a part of Julia. License is MIT: http://julialang.org/license
22

3+
using Base.Iterators.Enumerate
34

45
"""
56
AsyncCollector(f, results, c...; ntasks=0) -> iterator

base/broadcast.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ end
226226
else
227227
R = typejoin(eltype(B), S)
228228
new = similar(B, R)
229-
for II in take(iter, count)
229+
for II in Iterators.take(iter, count)
230230
new[II] = B[II]
231231
end
232232
new[I] = V

base/client.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ end
2323
# Create a docstring with an automatically generated list
2424
# of colors.
2525
const possible_formatting_symbols = [:normal, :bold]
26-
available_text_colors = collect(filter(x -> !isa(x, Integer), keys(text_colors)))
26+
available_text_colors = collect(Iterators.filter(x -> !isa(x, Integer), keys(text_colors)))
2727
available_text_colors = cat(1,
2828
sort(intersect(available_text_colors, possible_formatting_symbols), rev=true),
2929
sort(setdiff( available_text_colors, possible_formatting_symbols)))

base/dates/Dates.jl

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ module Dates
44

55
importall ..Base.Operators
66

7+
using Base.Iterators
8+
79
include("types.jl")
810
include("periods.jl")
911
include("accessors.jl")

base/deprecated.jl

+10
Original file line numberDiff line numberDiff line change
@@ -1023,4 +1023,14 @@ end))
10231023

10241024
@deprecate is (===)
10251025

1026+
@deprecate_binding Filter Iterators.Filter
1027+
@deprecate_binding Zip Iterators.Zip
1028+
@deprecate filter(flt, itr) Iterators.filter(flt, itr)
1029+
@deprecate_binding rest Iterators.rest
1030+
@deprecate_binding countfrom Iterators.countfrom
1031+
@deprecate_binding take Iterators.take
1032+
@deprecate_binding drop Iterators.drop
1033+
@deprecate_binding cycle Iterators.cycle
1034+
@deprecate_binding repeated Iterators.repeated
1035+
10261036
# End deprecations scheduled for 0.6

base/exports.jl

+3-9
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export
2323
Docs,
2424
Markdown,
2525
Threads,
26+
Iterators,
2627

2728
# Types
2829
AbstractChannel,
@@ -61,7 +62,6 @@ export
6162
Enumerate,
6263
Factorization,
6364
FileMonitor,
64-
Filter,
6565
FloatRange,
6666
Future,
6767
Hermitian,
@@ -124,7 +124,6 @@ export
124124
VersionNumber,
125125
WeakKeyDict,
126126
WorkerConfig,
127-
Zip,
128127

129128
# Ccall types
130129
Cchar,
@@ -958,16 +957,11 @@ export
958957

959958
# iteration
960959
done,
961-
enumerate,
962960
next,
963961
start,
962+
963+
enumerate, # re-exported from Iterators
964964
zip,
965-
rest,
966-
countfrom,
967-
take,
968-
drop,
969-
cycle,
970-
repeated,
971965

972966
# object identity and equality
973967
copy,

base/generator.jl

-8
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,6 @@ result, and algorithms that resize their result incrementally.
5555
iteratorsize(x) = iteratorsize(typeof(x))
5656
iteratorsize(::Type) = HasLength() # HasLength is the default
5757

58-
and_iteratorsize{T}(isz::T, ::T) = isz
59-
and_iteratorsize(::HasLength, ::HasShape) = HasLength()
60-
and_iteratorsize(::HasShape, ::HasLength) = HasLength()
61-
and_iteratorsize(a, b) = SizeUnknown()
62-
6358
abstract IteratorEltype
6459
immutable EltypeUnknown <: IteratorEltype end
6560
immutable HasEltype <: IteratorEltype end
@@ -81,9 +76,6 @@ values.
8176
iteratoreltype(x) = iteratoreltype(typeof(x))
8277
iteratoreltype(::Type) = HasEltype() # HasEltype is the default
8378

84-
and_iteratoreltype{T}(iel::T, ::T) = iel
85-
and_iteratoreltype(a, b) = EltypeUnknown()
86-
8779
iteratorsize{T<:AbstractArray}(::Type{T}) = HasShape()
8880
iteratorsize{I,F}(::Type{Generator{I,F}}) = iteratorsize(I)
8981
length(g::Generator) = length(g.iter)

base/iterator.jl renamed to base/iterators.jl

+19-37
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# This file is a part of Julia. License is MIT: http://julialang.org/license
22

3+
module Iterators
4+
5+
import Base: start, done, next, isempty, length, size, eltype, iteratorsize, iteratoreltype, indices, ndims
6+
7+
using Base: tuple_type_cons, SizeUnknown, HasLength, HasShape, IsInfinite, EltypeUnknown, HasEltype, OneTo
8+
9+
export enumerate, zip, rest, countfrom, take, drop, cycle, repeated, product, flatten, partition
10+
311
_min_length(a, b, ::IsInfinite, ::IsInfinite) = min(length(a),length(b)) # inherit behaviour, error
412
_min_length(a, b, A, ::IsInfinite) = length(a)
513
_min_length(a, b, ::IsInfinite, B) = length(b)
@@ -10,6 +18,14 @@ _diff_length(a, b, ::IsInfinite, ::IsInfinite) = 0
1018
_diff_length(a, b, ::IsInfinite, B) = length(a) # inherit behaviour, error
1119
_diff_length(a, b, A, B) = max(length(a)-length(b), 0)
1220

21+
and_iteratorsize{T}(isz::T, ::T) = isz
22+
and_iteratorsize(::HasLength, ::HasShape) = HasLength()
23+
and_iteratorsize(::HasShape, ::HasLength) = HasLength()
24+
and_iteratorsize(a, b) = SizeUnknown()
25+
26+
and_iteratoreltype{T}(iel::T, ::T) = iel
27+
and_iteratoreltype(a, b) = EltypeUnknown()
28+
1329
# enumerate
1430

1531
immutable Enumerate{I}
@@ -238,42 +254,6 @@ rest_iteratorsize(::IsInfinite) = IsInfinite()
238254
iteratorsize{I,S}(::Type{Rest{I,S}}) = rest_iteratorsize(iteratorsize(I))
239255

240256

241-
"""
242-
head_and_tail(c, n) -> head, tail
243-
244-
Returns `head`: the first `n` elements of `c`;
245-
and `tail`: an iterator over the remaining elements.
246-
247-
```jldoctest
248-
julia> a = 1:10
249-
1:10
250-
251-
julia> b, c = Base.head_and_tail(a, 3)
252-
([1,2,3],Base.Rest{UnitRange{Int64},Int64}(1:10,4))
253-
254-
julia> collect(c)
255-
7-element Array{Any,1}:
256-
4
257-
5
258-
6
259-
7
260-
8
261-
9
262-
10
263-
```
264-
"""
265-
function head_and_tail(c, n)
266-
head = Vector{eltype(c)}(n)
267-
s = start(c)
268-
i = 0
269-
while i < n && !done(c, s)
270-
i += 1
271-
head[i], s = next(c, s)
272-
end
273-
return resize!(head, i), rest(c, s)
274-
end
275-
276-
277257
# Count -- infinite counting
278258

279259
immutable Count{S<:Number}
@@ -677,7 +657,7 @@ end
677657

678658

679659
"""
680-
partition(collection, n) -> iterator
660+
partition(collection, n)
681661
682662
Iterate over a collection `n` elements at a time.
683663
@@ -723,3 +703,5 @@ function next(itr::PartitionIterator, state)
723703
end
724704
return resize!(v, i), state
725705
end
706+
707+
end

base/multidimensional.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ end
381381
# and ensure the value to set is either an AbstractArray or a Repeated scalar
382382
# before redispatching to the _unsafe_batchsetindex!
383383
_iterable(v::AbstractArray) = v
384-
_iterable(v) = repeated(v)
384+
_iterable(v) = Iterators.repeated(v)
385385
@inline function _setindex!{T,N}(l::LinearIndexing, A::AbstractArray{T,N}, x, J::Vararg{Union{Real,AbstractArray,Colon},N})
386386
@boundscheck checkbounds(A, J...)
387387
_unsafe_setindex!(l, A, x, J...)

base/pkg/resolve.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ function sanity_check(deps::Dict{String,Dict{VersionNumber,Available}},
6666

6767
vers = Array{Tuple{String,VersionNumber,VersionNumber}}(0)
6868
for (p,d) in deps, vn in keys(d)
69-
lvns = VersionNumber[filter(vn2->(vn2>vn), keys(d))...]
69+
lvns = VersionNumber[Iterators.filter(vn2->(vn2>vn), keys(d))...]
7070
nvn = isempty(lvns) ? typemax(VersionNumber) : minimum(lvns)
7171
push!(vers, (p,vn,nvn))
7272
end

base/pmap.jl

+39-5
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ function pgenerate(p::WorkerPool, f, c)
2424
return AsyncGenerator(f, c; ntasks=()->nworkers(p))
2525
end
2626
batches = batchsplit(c, min_batch_count = length(p) * 3)
27-
return flatten(AsyncGenerator(remote(p, b -> asyncmap(f, b)), batches))
27+
return Iterators.flatten(AsyncGenerator(remote(p, b -> asyncmap(f, b)), batches))
2828
end
2929
pgenerate(p::WorkerPool, f, c1, c...) = pgenerate(p, a->f(a...), zip(c1, c...))
3030
pgenerate(f, c) = pgenerate(default_worker_pool(), f, c)
@@ -133,7 +133,7 @@ function pmap(p::AbstractWorkerPool, f, c; distributed=true, batch_size=1, on_er
133133
f = wrap_on_error(f, (x,e)->BatchProcessingError(x,e); capture_data=true)
134134
end
135135
f = wrap_batch(f, p, on_error)
136-
results = collect(flatten(AsyncGenerator(f, batches; ntasks=()->nworkers(p))))
136+
results = collect(Iterators.flatten(AsyncGenerator(f, batches; ntasks=()->nworkers(p))))
137137
if (on_error !== nothing) || (retry_n > 0)
138138
process_batch_errors!(p, f_orig, results, on_error, retry_on, retry_n, retry_max_delay)
139139
end
@@ -213,6 +213,40 @@ function process_batch_errors!(p, f, results, on_error, retry_on, retry_n, retry
213213
nothing
214214
end
215215

216+
"""
217+
head_and_tail(c, n) -> head, tail
218+
219+
Returns `head`: the first `n` elements of `c`;
220+
and `tail`: an iterator over the remaining elements.
221+
222+
```jldoctest
223+
julia> a = 1:10
224+
1:10
225+
226+
julia> b, c = Base.head_and_tail(a, 3)
227+
([1,2,3],Base.Iterators.Rest{UnitRange{Int64},Int64}(1:10,4))
228+
229+
julia> collect(c)
230+
7-element Array{Any,1}:
231+
4
232+
5
233+
6
234+
7
235+
8
236+
9
237+
10
238+
```
239+
"""
240+
function head_and_tail(c, n)
241+
head = Vector{eltype(c)}(n)
242+
s = start(c)
243+
i = 0
244+
while i < n && !done(c, s)
245+
i += 1
246+
head[i], s = next(c, s)
247+
end
248+
return resize!(head, i), Iterators.rest(c, s)
249+
end
216250

217251
"""
218252
batchsplit(c; min_batch_count=1, max_batch_size=100) -> iterator
@@ -231,14 +265,14 @@ function batchsplit(c; min_batch_count=1, max_batch_size=100)
231265
end
232266

233267
# Split collection into batches, then peek at the first few batches
234-
batches = partition(c, max_batch_size)
268+
batches = Iterators.partition(c, max_batch_size)
235269
head, tail = head_and_tail(batches, min_batch_count)
236270

237271
# If there are not enough batches, use a smaller batch size
238272
if length(head) < min_batch_count
239273
batch_size = max(1, div(sum(length, head), min_batch_count))
240-
return partition(collect(flatten(head)), batch_size)
274+
return Iterators.partition(collect(Iterators.flatten(head)), batch_size)
241275
end
242276

243-
return flatten((head, tail))
277+
return Iterators.flatten((head, tail))
244278
end

base/promotion.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ if isdefined(Core, :Inference)
226226
end
227227
function _promote_op(op, R::ANY, S::ANY)
228228
F = typeof(a -> op(a...))
229-
G = Tuple{Generator{Zip2{Tuple{R},Tuple{S}},F}}
229+
G = Tuple{Generator{Iterators.Zip2{Tuple{R},Tuple{S}},F}}
230230
return Core.Inference.return_type(first, G)
231231
end
232232
else

base/show.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ function is_exported_from_stdlib(name::Symbol, mod::Module)
156156
end
157157
mod = parent
158158
end
159-
return isexported(mod, name) && isdefined(mod, name) && getfield(mod, name) === orig
159+
return isexported(mod, name) && isdefined(mod, name) && !isdeprecated(mod, name) && getfield(mod, name) === orig
160160
end
161161

162162
function show(io::IO, f::Function)

base/sysimg.jl

+3-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,9 @@ include("intset.jl")
129129
include("associative.jl")
130130
include("dict.jl")
131131
include("set.jl")
132-
include("iterator.jl")
132+
include("iterators.jl")
133+
using .Iterators: zip, enumerate
134+
using .Iterators: Flatten, product # for generators
133135

134136
# Definition of StridedArray
135137
typealias StridedReshapedArray{T,N,A<:DenseArray} ReshapedArray{T,N,A}

0 commit comments

Comments
 (0)