简体   繁体   English

Julia struct中的可变字段

[英]mutable fields in Julia struct

I couldn't find an answer in both stackoverflow and the Julia docs to the following "design problem": 我无法在stackoverflow和Julia文档中找到以下“设计问题”的答案:

Let's say I want to define the following object 假设我想定义以下对象

struct Person
birthplace::String
age::Int
end

Since Person is immutable, I'm happy that nobody can change the birthplace of any Person created, nonetheless, this also implies that when time passes, I cannot change their age either... 由于Person是不变的,我很高兴没有人可以改变所创造的任何Personbirthplace ,但是,这也意味着当时间过去,我也无法改变他们的age ......

On the other hand, if I define the type Person as 另一方面,如果我将Person类型定义为

mutable struct Person
birthplace::String
age::Int
end

I can now make them age , but I don't have the safety I had before on the birthplace , anyone can access it and change it. 我现在可以让他们age ,但我没有以前在birthplace的安全,任何人都可以访问它并改变它。

The workaround I found so far is the following 到目前为止我找到的解决方法如下

struct Person
birthplace::String
age::Vector{Int}
end

where obviously age is a 1-element Vector . 显然age是1元素Vector
I find this solution quite ugly and definitely suboptimal as I have to access the age with the square brackets every time. 我发现这个解决方案非常难看并且绝对不是最理想的,因为我每次都必须使用方括号访问年龄。

Is there any other, more elegant, way to have both immutable and mutable fields in an object? 是否还有其他更优雅的方法在对象中包含不可变字段和可变字段?

Maybe the problem is that I am missing the true value of having either everything mutable or immutable within a struct . 也许问题是我错过了在struct中拥有所有可变或不可变的真正价值。 If that's the case, could you explain me that? 如果是这样的话,你能解释一下吗?

For this particular example it seems better to store the birthdate rather than the age, since the birthdate is also immutable, and it is simple enough to calculate the age from that information, but perhaps this is just a toy example. 对于这个特殊的例子,最好存储生日,而不是年龄,因为生日也是不可改变的,并且从这些信息中计算年龄很简单,但也许这只是一个玩具的例子。


I find this solution quite ugly and definitely suboptimal as I have to access the age with the square brackets every time. 我发现这个解决方案非常难看并且绝对不是最理想的,因为我每次都必须使用方括号访问年龄。

Usually you would define a getter, ie something like age(p::Person) = p.age[1] that you use instead of accessing the field directly. 通常你会定义一个getter,比如你使用的age(p::Person) = p.age[1] ,而不是直接访问该字段。 With this you avoid the "ugliness" with the brackets. 这样你就可以避免括号中的“丑陋”。

In this case, where we only want to store a single value, it is also possible to use a Ref (or possibly a 0-dimensional Array ), something like: 在这种情况下,我们只想存储单个值,也可以使用Ref (或可能是0维Array ),例如:

struct Person
    birthplace::String
    age::Base.RefValue{Int}
end
Person(b::String, age::Int) = Person(b, Ref(age))
age(p::Person) = p.age[]

with usage: 用法:

julia> p = Person("earth", 20)
Person("earth", 20)

julia> age(p)
20

You've received some interesting answers, and for the "toy example" case, I like the solution of storing the birth-date. 你收到了一些有趣的答案,对于“玩具示例”的情况,我喜欢存储出生日期的解决方案。 But for more general cases, I can think of another approach that might be useful. 但对于更一般的情况,我可以想到另一种可能有用的方法。 Define Age as its own mutable struct, and Person as an immutable struct. Age定义为自己的可变结构,将Person定义为不可变结构。 That is: 那是:

julia> mutable struct Age ; age::Int ; end

julia> struct Person ; birthplace::String ; age::Age ; end

julia> x = Person("Sydney", Age(10))
Person("Sydney", Age(10))

julia> x.age.age = 11
11

julia> x
Person("Sydney", Age(11))

julia> x.birthplace = "Melbourne"
ERROR: type Person is immutable

julia> x.age = Age(12)
ERROR: type Person is immutable

Note that I can't alter either field of Person , but I can alter the age by directly accessing the age field in the mutable struct Age . 请注意,我不能改变Person任何一个字段,但我可以通过直接访问mutable struct Ageage字段来改变Age You could define an accessor function for this, ie: 您可以为此定义一个访问者函数,即:

set_age!(x::Person, newage::Int) = (x.age.age = newage)

julia> set_age!(x, 12)
12

julia> x
Person("Sydney", Age(12))

There is nothing wrong with the Vector solution discussed in another answer. 另一个答案中讨论的Vector解决方案没有任何问题。 It is essentially accomplishing the same thing, since array elements are mutable. 它基本上完成了同样的事情,因为数组元素是可变的。 But I think the above solution is neater. 但我认为上述解决方案更整洁。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM