我有一个不可变的结构,其中有四个对象定义如下:
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)))
我正在修改FltFric.muS
的值,如下所示:
FltFriction.muS[1:20] = 100
这很好用。但是当我尝试修改W的值时
FltFriction.W = (FltFriction.muS - FltFriction.muD)./(FltFriction.Dc)
这给了我一个错误:type FltFric is immutable
。
为什么第一个语句在第二个语句没有出错时会出错?如果类型是不可变的,则两个语句都应该给出错误。两个作业之间有什么区别?
我知道我可以通过输入mutable struct
来解决问题,但我不明白我的两项任务的区别。
答案 0 :(得分:7)
我不是朱莉娅专家,但我认为这是一个更普遍的问题。
在第一项作业中,您要修改列表FltFriction.muS
的某些元素。这很好,因为虽然结构是不可变的,但.muS
引用的列表是可变的。换句话说,您通过更改其元素来改变列表,而不是改变结构。
在第二个作业中,您尝试一下子替换整个列表.W
。在这种情况下,您试图直接改变结构,替换其中一个元素。因此,第二个分配失败,而第一个分配成功。
我在这里推测,但我怀疑如果你试图像这样做第二个任务:
FltFriction.W[1:end] = ...
然后你会没事的,因为你改变了列表而不是结构。
正如评论者所指出的那样(见下文),朱莉娅有一个更具惯用性(且性能更高)的#34;通过使用就地赋值运算符(neat!)来正确执行此操作而不改变结构本身的方法:
FltFriction.W .= (FltFriction.muS - FltFriction.muD)./FltFriction.Dc