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

Julia function signatures and sub-types, specifically String, ByteString

(使用 Julia 0.3.11) 我无法正确地对我的一些代码进行类型注释,在初始版本中我们一直使用 ASCIIString - 将任何字符串注释为 "avoid" 抽象类型,但让我们从示例开始,这可能与我在这里的一些讨论中看到的被称为 "triangular dispatch" 的内容有关:

# 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 的任何子类型(对吗?)例如 - 我想制作一个字符串字典 - 这是一个抽象类型,但是使用具体的键- 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)

一个解决方案是在 ( ) 中建议的 'convert'.

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

是否有推荐的代码库可供阅读以作为对惯用 Julia 代码的参考? 就像 Julia 的字典赋值运算符的实现一样。标准库中是否有一部分被认为可以作为参考?谢谢

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

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]

我可以推荐看看 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

我知道这只是您要求的一部分,但也许您觉得已经足够了。

你所说的 pushval! 可以使用 push!(get!(d1, "a", []), 1) 实现(尽管它将 return 附加到的字典值而不是字典本身)。如果你需要限制内部集合值的类型,你可以,例如,使用:

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

如果您真的需要将其定义为函数,恐怕目前您无法按照您描述的方式定义类型。作为 to the question you referenced notes, Julia does not implement triangular dispatch yet, although it is targeted for 0.5.