Julia:我们可以在不可变结构类型中更改对象多少?

Pri*_*kur 6 struct types julia

我有一个不可变的结构,有四个对象定义如下:

struct FltFric
    muS::Array{Float64, 2}
    muD::Array{Float64, 2}
    Dc::Float64
    W::Array{Float64, 2}
end

muS = repmat([0.6], 100, 1) # Coefficient of static friction
muD = repmat([0.5], 100, 1) # Coefficient of dynamic friction
Dc = 0.1                     # Critical slip distance

FltFriction = FltFric(muS, muD, Dc, zeros(size(muS)))
Run Code Online (Sandbox Code Playgroud)

我正在修改FltFric.muS如下的值:

FltFriction.muS[1:20] = 100
Run Code Online (Sandbox Code Playgroud)

这很好用.但是当我尝试修改W的值时

FltFriction.W = (FltFriction.muS - FltFriction.muD)./(FltFriction.Dc)
Run Code Online (Sandbox Code Playgroud)

这给了我一个错误:type FltFric is immutable.

为什么第一个语句在第二个语句出错时没有给出错误?如果类型是不可变的,则两个语句都应该给出错误.这两项任务有什么区别?

我知道我可以通过打字来解决问题mutable struct,但我不明白我的两个任务的区别.

bja*_*chi 9

我不是朱莉娅专家,但我认为这是一个更普遍的问题.

在第一个作业中,您正在修改列表中的某些元素FltFriction.muS.这很好,因为虽然结构是不可变的,但引用的列表.muS是可变的.换句话说,您通过更改其元素而不是改变结构来改变列表.

在第二个任务中,你试图.W一举取代整个列表.在这种情况下,您试图直接改变结构,替换其中一个元素.因此,第二个分配失败,而第一个分配成功.

我在这里猜测,但我怀疑如果你试图做第二次任务:

FltFriction.W[1:end] = ...

那你就没事了,因为你改变了列表而不是结构.

作为一个评论者指出的(见下文),在朱莉娅有一个"更地道(和更好的性能)"的方式正确,而不使用就地赋值运算符变异的结构本身做这个(纯!):

FltFriction.W .= (FltFriction.muS - FltFriction.muD)./FltFriction.Dc

  • 这是对的.而```可以是例如`1:end`.编写这个特定案例的更惯用(也更高效)的方法是`FltFriction.W.=(FltFriction.muS - FltFriction.muD)./ FltFriction.Dc`它将融合所有虚线运算符,并使用inplace assignment( `.=`)修改`W`数组. (3认同)
  • 注意`FltFriction.W.=(FltFriction.muS .- FltFriction.muD)./ FltFriction.Dc`或`@.FltFriction.W =(FltFriction.muS - FltFriction.muD)/ FltFriction.Dc`会更高效,因为缺少点意味着它融合成两部分而不是一部分. (3认同)