复合类型的 julia 静态字段

julia static field of composite type

在 Julia 中我可以创建和使用静态字段吗?让我用一个简化的例子来解释我的问题。假设我们有一个类型:

type Foo
  bar::Dict()
  baz::Int
  qux::Float64
  function Foo(fname,baz_value,qux_value)
     dict = JLD.load(fname)["dict"] # It is a simple dictionary loading from a special file
     new(dict,baz_value,quz_value)
  end
end

现在,如您所见,我从 jld 文件加载字典并将其与其他两个变量 bazqux_value 一起存储到 Foo 类型中。现在,假设我将创建 3 个 Foo 对象类型。

vars = [ Foo("mydictfile.jld",38,37.0) for i=1:3]

在这里,如您所见,所有 Foo 对象都加载同一个字典。这是一个很大的文件 (~10GB),我不想多次加载它。所以, 我只是想问一下,在 julia 中有什么方法可以让我只加载一次并且所有 3 种类型都可以访问它吗? (这就是我在问题中简单地使用 Static 关键字的方式)

对于这样一个简单的问题,我的方法可能看起来很愚蠢,但作为下一步,我使这个 Foo 类型可迭代,我需要在 next(d::Foo, state) 函数中使用这个字典。

编辑

其实我现在已经找到办法了。但我想问一下,这对不对。

而不是将文件名提供给 FOO 构造函数,如果我在创建对象之前将字典加载到变量中并将相同的变量提供给所有构造函数,我想所有的构造函数都只是创建指向同一个字典的指针,而不是一次又一次地创建。我对吗 ?

所以,修改后的版本将是这样的:

 dict = JLD.load("mydictfile.jld")["dict"]
 vars = [ Foo(dict,38,37.0) for i=1:3]

顺便说一句,我仍然想听听我是否完全在 Foo 类型中做同样的事情(我的意思是它的构造函数)

您正在通过添加内部构造函数创建类型 "too special"。如果您不提供内部构造函数,Julia 会提供默认构造函数;这些只是填充新类型对象中的字段。

所以你可以这样做:

immutable Foo{K,V}
    bar::Dict{K,V}
    baz::Int
    qux::Float64
end

dict = JLD.load("mydictfile.jld")["dict"]
vars = [Foo(dict, i, i+1) for i in 1:3]

请注意,在类型定义中 Dict 之后包含括号是一个语法错误。

{K,V} 使 Foo 类型参数化,这样你就可以制作不同种类的 Foo 类型,如果需要的话,里面有不同的 Dict 类型。即使您只将它用于单一类型的 Dict,这也会提供更高效的代码,因为类型参数 KV 将在您创建 Foo 时推断出来] 目的。请参阅 Julia 手册:http://docs.julialang.org/en/release-0.5/manual/performance-tips/#avoid-fields-with-abstract-containers

现在您甚至可以在没有 JLD 文件的情况下尝试代码(例如,我们没有):

julia> dict = Dict("a" => 1, "b" => 2)

julia> vars = [Foo(dict, i, Float64(i+1)) for i in 1:3]
3-element Array{Foo{String,Int64},1}:
 Foo{String,Int64}(Dict("b"=>2,"a"=>1),1,2.0)
 Foo{String,Int64}(Dict("b"=>2,"a"=>1),2,3.0)
 Foo{String,Int64}(Dict("b"=>2,"a"=>1),3,4.0)

你可以看到它确实是同一个字典(即只有一个引用实际上存储在类型对象中)通过修改其中一个并看到其他人也发生变化,即它们指向同一个字典对象:

julia> vars[1].bar["c"] = 10
10

julia> vars
3-element Array{Foo{String,Int64},1}:
 Foo{String,Int64}(Dict("c"=>10,"b"=>2,"a"=>1),1,2.0)
 Foo{String,Int64}(Dict("c"=>10,"b"=>2,"a"=>1),2,3.0)
 Foo{String,Int64}(Dict("c"=>10,"b"=>2,"a"=>1),3,4.0)