【问题标题】:Check if a type implements an interface in Julia检查一个类型是否在 Julia 中实现了一个接口
【发布时间】:2016-09-09 11:13:56
【问题描述】:

如何检查一个类型在 Julia 中实现了一个接口?

例如迭代接口由函数startnextdone实现。

我需要根据参数类型是否实现给定接口来对函数进行专门化。

编辑

这是我想做的一个例子。

考虑以下代码:

a = [7,8,9]
f = 1.0    
s = Set()
push!(s,30)
push!(s,40)

function getsummary(obj)
  println("Object of type ", typeof(obj))
end

function getsummary{T<:AbstractArray}(obj::T)
  println("Iterable Object starting with ", next(obj, start(obj))[1])
end

getsummary(a)
getsummary(f)
getsummary(s)

输出是:

Iterable Object starting with 7
Object of type Float64
Object of type Set{Any}

这是我们所期望的,因为Set 不是AbstractArray。但显然我的第二种方法只需要类型 T 来实现迭代接口。

我的问题不仅与迭代接口有关,还与一组函数定义的所有接口有关。

EDIT-2

我认为我的问题与

有关

https://github.com/JuliaLang/julia/issues/5

因为我们可以想象像T&lt;:Iterable这样的东西

【问题讨论】:

  • 如果我理解正确,你在找methodswith()?
  • @GnimucK。是的,类似的东西。但我没有看到使用methodswith() 实现动态调度的干净方法:我想定义两个函数,并根据类型是否实现接口来使用正确的函数。

标签: julia


【解决方案1】:

通常,这是通过特征完成的。一种实现见Traits.jl;在Base 中使用了类似的方法来调度Base.iteratorsizeBase.linearindexing 等。例如,Base 使用iteratorsize trait 实现collect

"""
    collect(element_type, collection)

Return an `Array` with the given element type of all items in a collection or iterable.
The result has the same shape and number of dimensions as `collection`.
"""
collect{T}(::Type{T}, itr) = _collect(T, itr, iteratorsize(itr))

_collect{T}(::Type{T}, itr, isz::HasLength) = copy!(Array{T,1}(Int(length(itr)::Integer)), itr)
_collect{T}(::Type{T}, itr, isz::HasShape)  = copy!(similar(Array{T}, indices(itr)), itr)
function _collect{T}(::Type{T}, itr, isz::SizeUnknown)
    a = Array{T,1}(0)
    for x in itr
        push!(a,x)
    end
    return a
end

另请参阅 Mauro Werder's talk 关于特征。

我将定义一个 iterability(::T) 特征如下:

immutable Iterable end
immutable NotIterable end
iterability(T) =
    if method_exists(length, (T,)) || !isa(Base.iteratorsize(T), Base.HasLength)
        Iterable()
    else
        NotIterable()
    end

这似乎有效:

julia> iterability(Set)
Iterable()

julia> iterability(Number)
Iterable()

julia> iterability(Symbol)
NotIterable()

【讨论】:

  • 谢谢。这绝对是我想要的。
【解决方案2】:

你可以通过methodswith检查a type是否实现an interface如下:

foo(a_type::Type, an_interface::Symbol) = an_interface ∈ [i.name for i in methodswith(a_type, true)]

julia> foo(EachLine, :done)
true

但是我不太明白你在评论中提到的动态调度方法,泛型函数是什么样的?函数的输入和输出是什么?我猜你想要这样的东西?

function foo(a_type::Type, an_interface::Symbol)
    # assume bar baz are predefined
    if an_interface ∈ [i.name for i in methodswith(a_type, true)]
        # call function bar
    else 
        # call function baz
    end
end

或一些元编程的东西在编译时分别生成这些函数?

【讨论】:

  • 我了解您的解决方案,但是这个 julia 代码比相应的 java 代码更冗长:) 在 Julia 中没有更简洁的方法来检查它吗?
  • @IssamT。所以问题可以简化为merely knowing a type/"class" `T`, how to find its "methods"?。由于 julia 具有多分派的特点,类没有自己的方法,所以这个过程比其他 oop 语言如 python 和 java 稍微难一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-01
  • 1970-01-01
  • 2018-11-16
  • 2010-11-10
  • 2012-05-29
  • 2014-09-02
相关资源
最近更新 更多