当我试图做一个复合型与矩阵作为现场堆栈溢出

问题描述 投票:4回答:2

在下面的代码,我有一个复合型,在我真正的代码的几个字段都是矩阵。在这个例子中只有1我不断收到堆栈溢出,当我尝试构建复合型。下面是代码示例:

struct Tables
    eij::Array{Float64,2}
end

Tables(eij::Array{Float64,2}) = Tables(eij) # works if this is commented out
x = 5   # arbitrary matrix dimension    
e_ij = Array{Float64,2}(undef,x,x)

for i=1:x
    for j=1:x
        e_ij[i,j] = i*j/2.3     #dummy numbers, but not the case in real code
    end
end

vdwTable = Tables([e_ij[i,j] for i=1:x,j=1:x])

我用的是临时变量e_ij使第一,因为我不想复合Tables是可变的矩阵。所以,我的理由是,在像e_ij虚拟变量首先生成表格,然后我就可以初始化不变Tables我真正想要的。

如果我注释掉Tables它的工作原理与结构外的构造。不过,其实我是想有几个不同的外部构造函数,其中不同的字段不传递的数据进行初始化的情况。在这种情况下,我想给他们默认矩阵。

我得到的错误是:ERROR: LoadError: StackOverflowError:上线vdwTable = Tables([e_ij[i,j] for i=1:x,j=1:x])

julia
2个回答
5
投票

当定义一个复合类型,内部构造被自动定义,所以这样的:

struct Tables
    eij::Array{Float64,2}
end

相当于这个:

struct Tables
    eij::Array{Float64,2}
    Tables(eij::Array{Float64,2}) = new(eij)
end

当你定义了该外构造

Tables(eij::Array{Float64,2}) = Tables(eij)

你在内部构造的方式获得。直到你得到一个堆栈溢出你的外部构造只是递归调用自己。

这样做,在另一方面,

Tables(eij) = Tables(eij)

其实就相当于这个:

Tables(eij::Any) = Tables(eij)

所以,当你调用随后

vdwTable = Tables([e_ij[i,j] for i=1:x,j=1:x])

那么它只是忽略了你的外部构造,因为有一个更具体的方法匹配,即内部构造。因此,该特定外部构造还是蛮有用的,它要么被忽略,或者它会重复,直至堆栈溢出。

最简单的解决方法是:只是不要让外部的构造。如果你确实需要一个外执行某些条件下,确保它不具有相同类型的签名阴影内部构造。例如,

Tables() = Tables(zero(5, 5))

应该管用。

我可能会做这样的,虽然:

struct Tables
    eij::Array{Float64,2}
    Tables(eij=zeros(5, 5)) = new(eij)
end

对于你的第二个例子,有两个字段,你可以试试这个:

struct Tables
    eij::Array{Float64,2}
    sij::Array{Float64,2}
    Tables(eij=zeros(5,5), sij=zeros(5,5)) = new(eij, sij)
end

您的输入将被转换为Float64矩阵,如果这是可能的,否则将引发异常。


5
投票

DNF给予了适当的解释,以便+1。我只想补充一个小评(不回答这个问题,但东西是从我的经验有关),是太长了评论。

如果省略了指定的内部构造自己朱莉娅自动定义一个内部和一个外部的构造函数:

julia> struct Tables
           eij::Array{Float64,2}
       end

julia> methods(Tables)
# 2 methods for generic function "(::Type)":
[1] Tables(eij::Array{Float64,2}) in Main at REPL[1]:2
[2] Tables(eij) in Main at REPL[1]:2

而限定内部构造抑制了外构造的定义:

julia> struct Tables
           eij::Array{Float64,2}
           Tables(eij::Array{Float64,2}) = new(eij)
       end

julia> methods(Tables)
# 1 method for generic function "(::Type)":
[1] Tables(eij::Array{Float64,2}) in Main at REPL[1]:3

所以情况是不等价的100%。自动生成的外构造的目的是,如果有可能进行它的参数的自动转换,例如参见(这是结果在第一种情况下 - 的定义没有内部构造时):

julia> @code_lowered Tables([true false
       true false])
CodeInfo(
1 ─ %1 = (Core.apply_type)(Main.Array, Main.Float64, 2)
│   %2 = (Base.convert)(%1, eij)
│   %3 = %new(Main.Tables, %2)
└──      return %3
)

而在第二种情况下,同样的调用会抛出一个方法错误。

© www.soinside.com 2019 - 2024. All rights reserved.