diff --git a/src/Utilities/Utilities.jl b/src/Utilities/Utilities.jl index 6ab5ba9c8a..b7a0915c0c 100644 --- a/src/Utilities/Utilities.jl +++ b/src/Utilities/Utilities.jl @@ -30,5 +30,6 @@ include("cachingoptimizer.jl") include("universalfallback.jl") include("CleverDicts.jl") +include("lazy_iterators.jl") end # module diff --git a/src/Utilities/lazy_iterators.jl b/src/Utilities/lazy_iterators.jl new file mode 100644 index 0000000000..a7b44938a9 --- /dev/null +++ b/src/Utilities/lazy_iterators.jl @@ -0,0 +1,34 @@ +struct EmptyVector{T} <: AbstractVector{T} end +Base.size(::EmptyVector) = (0,) +Base.isempty(::EmptyVector) = true +Base.eltype(::EmptyVector{T}) where {T} = T +Base.iterate(::EmptyVector) = nothing + +""" + struct LazyMap{T, VT} + f::Function + data::VT + end + +Iterator over the elements of `data` mapped by `f`. This is similar to +`Base.Generator(f, data)` except that the `eltype` of a `LazyMap` is given at +construction while the `eltype` of `Base.Generator(f, data)` is `Any`. +""" +struct LazyMap{T, VT} + f::Function + data::VT +end +function LazyMap{T}(f::Function, data) where {T} + return LazyMap{T, typeof(data)}(f, data) +end +Base.size(it::LazyMap) = size(it.data) +function Base.iterate(it::LazyMap, args...) + elem_state = iterate(it.data, args...) + if elem_state === nothing + return nothing + else + return it.f(elem_state[1]), elem_state[2] + end +end +Base.IteratorSize(it::LazyMap) = Base.IteratorSize(it.data) +Base.eltype(::LazyMap{T}) where {T} = T diff --git a/test/Utilities/Utilities.jl b/test/Utilities/Utilities.jl index df160637c0..b1d041221b 100644 --- a/test/Utilities/Utilities.jl +++ b/test/Utilities/Utilities.jl @@ -31,3 +31,6 @@ end @testset "CleverDicts" begin include("CleverDicts.jl") end +@testset "Lazy iterators" begin + include("lazy_iterators.jl") +end diff --git a/test/Utilities/lazy_iterators.jl b/test/Utilities/lazy_iterators.jl new file mode 100644 index 0000000000..9da31338b6 --- /dev/null +++ b/test/Utilities/lazy_iterators.jl @@ -0,0 +1,25 @@ +using Test +using MathOptInterface +const MOI = MathOptInterface +const MOIU = MOI.Utilities + +@testset "EmptyVector{$T}" for T in [Int, Float64] + v = MOIU.EmptyVector{T}() + @test size(v) == (0,) + @test isempty(v) + @test eltype(v) == T + @test iterate(v) === nothing + c = collect(v) + @test c isa Vector{T} + @test isempty(c) +end + +@testset "LazyMap{$T}" for T in [Int, Float64] + v = MOIU.LazyMap{T}(x -> x^2, [2, 3]) + @test size(v) == (2,) + @test !isempty(v) + @test eltype(v) == T + c = collect(v) + @test c isa Vector{T} + @test c == [4, 9] +end