【问题标题】:julia static field of composite type复合类型的julia静态字段
【发布时间】:2016-11-10 12:02:19
【问题描述】:

我可以在 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),我不想多次加载它。所以, 我只是问,朱莉娅有什么办法,我只加载一次,所有 3 种类型都可以到达吗? (这就是我在问题中简单地使用静态关键字的方式)

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

编辑

其实,我现在已经找到了办法。但我想问一下,这是否正确。

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

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

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

顺便说一下,我还是想听听我是否完全在 Foo 类型内部做同样的事情(我的意思是它的构造函数)

【问题讨论】:

    标签: julia iterable


    【解决方案1】:

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

    【讨论】:

    • @David_P._Sanders 首先,很抱歉我的代码导致的错误。原因很简单,我需要在它的next函数中使用dict:next(d::Foo, state)有没有其他方法可以在它的next函数中使用dict文件而不将其存储为类型字段?
    • 首先,很抱歉我的代码导致的错误。原因很简单,我需要在它的下一个函数中使用dict:next(d::Foo, state)有没有其他方法可以在下一个函数中使用dict文件而不将其存储为类型字段?@DavidP.Sanders
    • 好的,那么在类型中存储对字典的引用似乎是一个很好的解决方案。编辑:我已从我的回答中删除了该评论。
    • 我也忘记了答案的第一部分。使用bar::Dict{K,V} 之类的参数类型不会使代码变慢吗?我在手册中读到了类似的内容,这就是为什么我总是尝试使用它们。
    • 不,恰恰相反:您应该使用参数类型。见手册:docs.julialang.org/en/release-0.5/manual/performance-tips/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-25
    • 2012-06-14
    • 2013-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-27
    相关资源
    最近更新 更多