Julia静态字段的复合类型



我可以在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类型(我的意思是它的构造函数)中完全做同样的事情

通过添加内部构造函数使类型"太特殊"。如果你不提供内部构造函数,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)