为什么我们需要`iteratoreltype()`?

时间:2017-11-22 15:58:08

标签: julia

我不确定我理解为什么需要class Character(object): def __init__(self): self.NAME = '' self.life = 50 players = ["red","green","blue","yellow"] dict_players = {} for player in players: dict_players[player] = Character() 。每个iterable都保证生成__str__类型的对象,所以如果你不知道更好,那么你总是默认为那个。区分“我知道它可能是任何东西”(IteratorEltype())和“我不知道它是什么,因此它可以是任何东西”(Any)?

使用IteratorEltype == HasEltype && eltype = Any我可以找到的基本朱莉娅中的唯一类型是IteratorEltype == EltypeUnknown,这是EltypeUnknown()语法背后的工具。我可以想象,如果Generator是非叶类型,很难/不可能找到这样的生成器的(f(i) for i in iter),但不仅仅是将eltype设置为eltype(iter)在这种情况下?当然,如果eltype是叶类型且Any是类型稳定的,那么您不希望它是Any,但这两种情况在编译时应该是可区分的。

1 个答案:

答案 0 :(得分:0)

两个IteratorEltype()选项之间的区别如下:

  • HasEltype()说,即使eltype()比迭代器中实际遇到的类型更通用,也应将迭代器的值视为类型eltype()的对象。

  • EltypeUnknown()要求类似collect()的函数找出适用于所有元素的最特定类型。


示例:

julia> abstract type Wrapper end
       Base.length(w::Wrapper) = length(w.data)
       Base.iterate(w::Wrapper, s...) = iterate(w.data, s...)

       struct EltypeWrapper{T,D} <: Wrapper
           data::D
       end
       EltypeWrapper{T}(data) where T = EltypeWrapper{T,typeof(data)}(data)
       Base.eltype(::Type{<:EltypeWrapper{T}}) where T = T

       struct EltypeUnknownWrapper{D} <: Wrapper
           data::D
       end
       Base.IteratorEltype(::Type{<:EltypeUnknownWrapper}) = Base.EltypeUnknown()

julia> collect(EltypeWrapper{Any}(Any[1,2.0]))
2-element Array{Any,1}:
 1  
 2.0

julia> collect(EltypeUnknownWrapper(Any[1,2.0]))
2-element Array{Real,1}:
 1  
 2.0

请注意,两个数组具有相同的条目,但第一个数组的类型为Vector{Any},而第二个数组的类型为Vector{Real}


似乎HasEltype()应该更有效,因为它允许在collect()之类的函数中预先分配输出。朱莉娅(Julia)很擅长推导迭代器Eltype,并且EltypeUnknown()可以和HasEltype()一样快(或者由于某些奇怪的原因甚至比julia> using BenchmarkTools abstract type AbstractIterable end struct TypedIterable <: AbstractIterable; end struct UntypedIterable <: AbstractIterable; end Base.length(::AbstractIterable) = 100000 Base.eltype(::Type{TypedIterable}) = Int Base.IteratorEltype(::Type{UntypedIterable}) = Base.EltypeUnknown() function Base.iterate(f::AbstractIterable,i = 1) i > length(f) && return nothing return i, i+1 end @btime collect(UntypedIterable()) @btime collect(TypedIterable()) ; 43.033 μs (2 allocations: 781.33 KiB) 56.772 μs (2 allocations: 781.33 KiB) 快):

IteratorEltype()

EltypeUnknown()因此不一定会影响使用迭代器的性能,但可能会严重影响调用堆栈中进一步的性能。如果对非叶子类型进行操作,则几乎所有代码的速度都快几个数量级,因此将IteratorEltype()设置为eltype()并希望将IteratorEltype() = HasEltype()简化为而不是先设置eltype(),然后再将git log --graph --oneline --decorate --pretty=format:"%cn committed %h on %cd" 设置为某种抽象类型。