Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Julia: How much can we change the objects in immutable struct type?

I have an immutable structure with four objects defined as follows:

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)))

I am modifying the values of FltFric.muS as follows:

FltFriction.muS[1:20] = 100

This works fine. But when I try to modify the value of W

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

This gives me an error: type FltFric is immutable.

Why does the first statement not give error while the second one does? If the type is immutable, both statements should give an error. What is the difference between the two assignments?

I know that I can circumvent the problem by typing mutable struct, but I don't understand the difference in my two assignments.

like image 320
Prithvi Thakur Avatar asked May 03 '18 19:05

Prithvi Thakur


People also ask

What is a mutable struct in Julia?

type and immutable are valid up to julia 0.6, mutable struct and struct are the names of the same objects in julia 0.6 and forward. mutable in mutable struct means that the fields can change - which is actually fairly rarely used so being immutable is the default. mutable struct 's are slower than struct s.

Is struct immutable?

Yep, you're right, structs are not immutable. The thing about structs is that they are values. That means every variable is considered a copy, and its members are isolated from changes made to other variables. Structs are not copied on mutation.

Why should struct be immutable?

Creating mutable structs can lead to all kinds of strange behavior in your application and, therefore, they are considered a very bad idea (stemming from the fact that they look like a reference type but are actually a value type and will be copied whenever you pass them around).


1 Answers

I am not a Julia expert, but I think this is a more general question.

In the first assignment, you're modifying certain elements of the list FltFriction.muS. This is fine since although the struct is immutable, the list referred to by .muS is mutable. In other words, you're mutating the list by changing its elements, rather than mutating the struct.

In the second assignment, you're trying to replace the entire list .W in one fell swoop. In this case you're trying to mutate the struct directly, replacing one of its elements. For this reason, the second assignment fails while the first one succeeds.

I'm speculating here, but I suspect that if you tried to do the second assignment like so:

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

Then you would be fine, since you're mutating the list instead of the struct.

As pointed out by a commenter (see below), in Julia there is a "more idiomatic (and more performant)" way to do this correctly and without mutating the struct itself by using the in-place assignment operator (neat!):

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

like image 141
bjarchi Avatar answered Dec 06 '22 17:12

bjarchi