Is it possible to realize a bi-directional relativistic connection between two structures using only constant properties?

My use case is based on the following model:

struct Person { let name: String let houses: [House] } struct House { let owner: Person } 

Now, ideally, I would like to maintain a bi-directional relationship in which each house should have exactly one owner, where the owner should also know all his houses.

Using the above data structures, is it possible to create House and Person instances in such a way that there is a relationship between them, and the objects essentially point to each other?

I assume that the wording of this is already somewhat misleading, because because of the semantics of the values ​​of struct s, they actually do not indicate anything, but contain only copies of the values. It seems like it should be obvious that it's impossible to create these two objects with a bi-directional ratio, but I still wanted to be sure and ask the following questions here!

The obvious solution would also be to make the houses and owner variables using var instead of let when declaring them, then communication can be maintained in the initializer of each struct :

 struct Person { let name: String var houses: [House] init(name: String, houses: [House]) { self.name = name self.houses = houses self.houses = houses.map { (house: House) in var newHouse = house newHouse.owner = self return newHouse } } } struct House { var owner: Person init(owner: Person) { self.owner = owner var newHouses = self.owner.houses newHouses.append(self) self.owner = Person(name: owner.name, houses: newHouses) } } 

However, what if I want to keep the houses and owner constant? As I said, it seems obvious that this is impossible, but I wonder if there is any weird (possibly functional) way to achieve this? I was thinking about lenses , which can be used as getters and setters when working with immutable models.

+6
source share
2 answers

What you describe is more like ORM than linguistic, and also not suitable for handling value types such as structs. How do you expect the language to recognize that owner is a feedback property of houses and needs to be supported accordingly? This is something that needs to be done with code, not with Swift.

It looks like you are trying to save some kind of graphical model object, which is a problem that has been solved many times. You should take a look at Realm DB and Basic Data as which managed bi-directional relationships are offered. However, you will find that none of them are implemented using structures. The problem with using value types is that they are copied to the record. As soon as you mutate one structure in the graph of objects, you need to reassign all related things with a new, mutated copy, which then in turn mutates and should update all related structures. Referential semantics (classes) simplifies the preservation of the graph of an object, since mutations do not create new instances.

+4
source

What you want is not possible with structs. Your current solution (with var ) does not work the way you think: all values ​​are independent copies. Consider the following example:

 let p = Person(name: "Nick", houses: []) let h = House(owner: p) h.owner.houses p.houses 

Since each copy is independent, this means that p does not match h.owner .

If you need bidirectional communication, you should use objects with weak pointers (to break the reference loop). Alternatively, you might think about whether you need to use a bi-directional relationship.

+2
source

All Articles