Julia函数签名和子类型,特别是String,ByteString

时间:2015-10-04 13:53:32

标签: templates types julia dispatch

(使用Julia 0.3.11) 我无法正确地对我的一些代码进行类型注释,在我们使用ASCIIString的初始版本中 - 注释任何String,以“避免”抽象类型,但让我们从示例开始,这可能与我在一些讨论中所看到的“三角调度”相关:

# How to type annotate this (sortof "Dictionary with default)
function pushval!(dict, key, val)
  key in keys(dict) ? push!(dict[key], val) : dict[key] = [val]
  return dict
end

d1 = Dict{ASCIIString, Vector{Int}}()
d2 = Dict{String, Vector{Int}}()

pushval!(d1, "a", 1)
pushval!(d2, "a", 1)

好的(首先 - 如果有一种更惯用的方法来构建一个带有默认值的字典,在这种情况下是一个空数组,我很乐意听到它)

所以现在,我尝试输入注释:

function pushval!{K, V} (dict::Dict{K, Vector{V}} , key, val)

更多的记录和工作。 但现在变得比较棘手了 - 我希望'key'成为K的任何子类型,而val - V的任何子类型(对吧?)例如 - 我想创建一个String字典 - 这是一个抽象类型,但是使用具体键 - ASCIIString / ByteString / UTF8String,

我想我应该写下列其中一项:

function pushval!{K, V} (dict::Dict{K, Vector{V}} , key::KK <: K, val:: VV <: V)
function pushval!{K, V, KK <: K, VV <: V} (dict::Dict{K, Vector{V}} , key::KK, val::VV)

一个解决方案就是在(Can I use a subtype of a function parameter in the function definition?)中建议使用'convert'。

但这整件事让我想起了我正在编写的Julia代码,我已经开始编写一个系统 - 使用String,FloatingPoint,Number和这样的抽象类型,当我实际尝试运行它时,我已经恢复了把所有东西都转换成具体的类型只是为了让东西现在运行......

是否有推荐的代码库作为对惯用Julia代码的引用? 就像Julia的字典赋值运算符的实现一样。是否有一部分标准库被认为是一个很好的参考?感谢

3 个答案:

答案 0 :(得分:2)

虽然我不太喜欢这个解决方案(性能低下),但它可能会有所帮助:

function pushval!{K, V} (dict::Dict{K, Vector{V}} , key , val)
  fun = function inner{tt1<:K,tt2<:V}(key::tt1,val::tt2)
   key in keys(dict) ? push!(dict[key], val) : dict[key] = [val]
   return dict
  end
  return fun(key,val)
end
# => pushval! (generic function with 1 method)
d1 = Dict{ASCIIString, Vector{Int}}()
# => Dict{ASCIIString,Array{Int32,1}} with 0 entries
d2 = Dict{String, Vector{Int}}()
# => Dict{String,Array{Int32,1}} with 0 entries

pushval!(d1, "a", 1)
# => Dict{ASCIIString,Array{Int32,1}} with 1 entry:
#    "a" => [1]

pushval!(d2, "a", 1)
# => Dict{String,Array{Int32,1}} with 1 entry:
#    "a" => [1]

答案 1 :(得分:1)

我知道这只是你要求的部分内容,但也许你觉得它已经足够了。

使用pushval!可以实现所谓的push!(get!(d1, "a", []), 1)(虽然它会返回附加到字典值的字典值而不是字典本身)。如果需要约束内部集合值的类型,则可以使用:

push!(get!(d1, "a", Number[]), 1)

如果你真的需要将它定义为一个函数,我恐怕目前你无法按照你描述的方式定义类型。作为您引用注释的问题的accepted answer,Julia尚未实现三角形调度,尽管it is targeted for 0.5

答案 2 :(得分:0)

我可以推荐Julia Style Guide。关于使用类型注释有一些建议。

对于您的情况,您根本不需要pushval!函数的类型注释。 Julia将从Dict创建中获取足够的信息,并为pushval!参数推导出适当的类型。

function pushval!(dict, key, val)
    key in keys(dict) ? push!(dict[key], val) : dict[key] = [val]
    return dict
end

d = Dict{String, Vector{Int} # Here is all annotations you need.

pushval!(d, "a", 1) # OK, "a" is ASCIIString which is subtype of AbstractString
pushval!(d, 1, 1) # ERROR, 1 is Int64 which is not subtype of AbstractString