代码之家  ›  专栏  ›  技术社区  ›  Prithvi Thakur

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

  •  6
  • Prithvi Thakur  · 技术社区  · 6 年前

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

    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 ,但我不明白我的两份作业有什么不同。

    1 回复  |  直到 6 年前
        1
  •  11
  •   bjarchi    6 年前

    我不是茱莉亚专家,但我认为这是一个更一般的问题。

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

    在第二个作业中,您试图替换整个列表 .W 一下子。在这种情况下,您试图直接改变结构,替换其中一个元素。因此,第二次分配失败,而第一次分配成功。

    我在这里推测,但我怀疑如果你尝试这样做第二个作业:

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

    那么您就可以了,因为您正在修改列表而不是结构。

    正如一位评论者所指出的(见下文),在Julia中,有一种“更惯用(和更高性能)”的方法可以正确地做到这一点,而不必通过使用就地赋值操作符(整洁!)改变结构本身:

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