10
10
end
11
11
12
12
Iterators over the tuples that are produced by a nested for loop.
13
- For instance, if `length(iterators) == 3` , this corresponds to the tuples
14
- `(i1, i2, i3)` produced by:
15
- ```
13
+
14
+ Construct a `NestedIterator` using [`nested`](@ref).
15
+
16
+ ## Example
17
+
18
+ If `length(iterators) == 3` ,
19
+ ```julia
20
+ x = NestedIterator(iterators, condition)
21
+ for (i1, i2, i3) in x
22
+ # produces (i1, i2, i3)
23
+ end
24
+ ````
25
+ is the same as
26
+ ```julia
16
27
for i1 in iterators[1]()
17
28
for i2 in iterator[2](i1)
18
29
for i3 in iterator[3](i1, i2)
@@ -28,40 +39,69 @@ struct NestedIterator{T,C}
28
39
iterators:: T # Tuple of functions
29
40
condition:: C
30
41
end
42
+
43
+ """
44
+ nested(iterators...; condition = (args...) -> true)
45
+
46
+ Create a [`NestedIterator`](@ref).
47
+
48
+ ## Example
49
+
50
+ ```julia
51
+ nested(1:2, ["A", "B"]; condition = (i, j) -> isodd(i) || j == "B")
52
+ ```
53
+ """
31
54
function nested (iterators... ; condition = (args... ) -> true )
32
55
return NestedIterator (iterators, condition)
33
56
end
57
+
34
58
Base. IteratorSize (:: Type{<:NestedIterator} ) = Base. SizeUnknown ()
59
+
35
60
Base. IteratorEltype (:: Type{<:NestedIterator} ) = Base. EltypeUnknown ()
36
- function next_iterate (iterators, condition, elems, states, iterator, elem_state)
61
+
62
+ function _next_iterate (
63
+ iterators,
64
+ condition,
65
+ elems,
66
+ states,
67
+ iterator,
68
+ elem_state,
69
+ )
37
70
while true
38
- elem_state === nothing && return nothing
71
+ if elem_state === nothing
72
+ return
73
+ end
39
74
elem, state = elem_state
40
- elems_states = first_iterate (
75
+ elems_states = _first_iterate (
41
76
Base. tail (iterators),
42
77
condition,
43
78
(elems... , elem),
44
79
(states... , (iterator, state, elem)),
45
80
)
46
- elems_states != = nothing && return elems_states
47
- # This could be written as a recursive function where we call `next_iterate`
48
- # here with this new value of `next_iterate` instead of the `while` loop`.
49
- # However, if there are too many consecutive elements for which `condition`
50
- # is `false` for the last iterator, this will result in a `StackOverflow`.
51
- # See https://github.com/jump-dev/JuMP.jl/issues/2335
81
+ if elems_states != = nothing
82
+ return elems_states
83
+ end
84
+ # This could be written as a recursive function where we call
85
+ # `_next_iterate` here with this new value of `_next_iterate` instead of
86
+ # the `while` loop`.
87
+ #
88
+ # However, if there are too many consecutive elements for which
89
+ # `condition`is `false` for the last iterator, this will result in a
90
+ # `StackOverflow`. See https://github.com/jump-dev/JuMP.jl/issues/2335
52
91
elem_state = iterate (iterator, state)
53
92
end
54
93
end
55
- function first_iterate (:: Tuple{} , condition, elems, states)
94
+
95
+ function _first_iterate (:: Tuple{} , condition, elems, states)
56
96
if condition (elems... )
57
97
return elems, states
58
- else
59
- return nothing
60
98
end
99
+ return
61
100
end
62
- function first_iterate (iterators, condition, elems, states)
101
+
102
+ function _first_iterate (iterators, condition, elems, states)
63
103
iterator = iterators[1 ](elems... )
64
- return next_iterate (
104
+ return _next_iterate (
65
105
iterators,
66
106
condition,
67
107
elems,
@@ -70,9 +110,11 @@ function first_iterate(iterators, condition, elems, states)
70
110
iterate (iterator),
71
111
)
72
112
end
73
- tail_iterate (:: Tuple{} , condition, elems, states, prev_states) = nothing
74
- function tail_iterate (iterators, condition, elems, states, prev_states)
75
- next = tail_iterate (
113
+
114
+ _tail_iterate (:: Tuple{} , condition, elems, states, prev_states) = nothing
115
+
116
+ function _tail_iterate (iterators, condition, elems, states, prev_states)
117
+ next = _tail_iterate (
76
118
Base. tail (iterators),
77
119
condition,
78
120
(elems... , states[1 ][3 ]),
@@ -83,7 +125,7 @@ function tail_iterate(iterators, condition, elems, states, prev_states)
83
125
return next
84
126
end
85
127
iterator = states[1 ][1 ]
86
- return next_iterate (
128
+ return _next_iterate (
87
129
iterators,
88
130
condition,
89
131
elems,
@@ -92,12 +134,15 @@ function tail_iterate(iterators, condition, elems, states, prev_states)
92
134
iterate (iterator, states[1 ][2 ]),
93
135
)
94
136
end
137
+
95
138
function Base. iterate (it:: NestedIterator )
96
- return first_iterate (it. iterators, it. condition, tuple (), tuple ())
139
+ return _first_iterate (it. iterators, it. condition, tuple (), tuple ())
97
140
end
141
+
98
142
function Base. iterate (it:: NestedIterator , states)
99
- return tail_iterate (it. iterators, it. condition, tuple (), states, tuple ())
143
+ return _tail_iterate (it. iterators, it. condition, tuple (), states, tuple ())
100
144
end
145
+
101
146
function _eltype_or_any (:: NestedIterator{<:Tuple{Vararg{Any,N}}} ) where {N}
102
147
return NTuple{N,Any}
103
148
end
0 commit comments