Юлия: Насколько мы можем изменить объекты в неизменяемом типе структуры? - PullRequest
0 голосов
/ 03 мая 2018

У меня есть неизменная структура с четырьмя объектами, определенными следующим образом:

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 Ответ

0 голосов
/ 03 мая 2018

Я не эксперт Юлии, но я думаю, что это более общий вопрос.

В первом назначении вы изменяете определенные элементы списка FltFriction.muS. Это хорошо, поскольку, хотя структура неизменна, список, на который указывает .muS, является изменяемым. Другими словами, вы изменяете список, изменяя его элементы, а не изменяя структуру.

Во втором задании вы пытаетесь заменить весь список .W одним махом. В этом случае вы пытаетесь изменить структуру напрямую, заменив один из ее элементов. По этой причине второе назначение не выполняется, а первое - успешно.

Я размышляю здесь, но подозреваю, что если вы попытаетесь выполнить второе задание следующим образом:

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

Тогда все будет в порядке, поскольку вы изменяете список вместо структуры.

Как указал комментатор (см. Ниже), в Julia есть «более идиоматический (и более производительный)» способ сделать это правильно и без изменения самой структуры с помощью оператора присваивания на месте (аккуратно! ):

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

...