my.node.a = "a1"
my.node.b = "b1"
The problem is that here you are proposing to use dot-notation. This is a built-in piece of Swift syntax; you don't get to redefine it. Thus you cannot talk like this unless my
is an instance of a class with an instance property node
, and node
is an instance of a class with instance properties a
and b
. And ex hypothesi they aren't.
In other words, you can certainly do what you want to do (construct a hierarchy of nodes), but you can't fetch their values using the syntax you are describing. This is not Ruby (or similar) where you get to interfere in the message-sending mechanism.
So, my first cut at the sort of hierarchical structure you describe would look like this (and you'll see at once that I'm using exactly the sort of notation you would prefer not to use!):
class Thing {
var val : String
var d = [String:Thing]()
init(_ val:String) {self.val = val}
subscript(key:String) -> Thing {
return self.d[key]!
}
}
let my = Thing("n")
let a = Thing("a1")
let b = Thing("b1")
let x = Thing("x2")
b.d["x"] = x
my.d["a"] = a
my.d["b"] = b
let result1 = my.val
let result2 = my["a"].val
let result3 = my["b"].val
let result4 = my["b"]["x"].val
What I can do for you is eliminate the double subscripting of ["b"]["x"]
. To do that, we need to reinvent key paths. (I say "reinvent" because NSObject already has this.) Thus, if we define Thing like this:
class Thing {
var val : String
var d = [String:Thing]()
init(_ val:String) {self.val = val}
subscript(key:String) -> Thing {
let path = split(key, {$0=="."}, maxSplit: 1)
if path.count == 2 {
return self.d[path[0]]![path[1]]
}
return self.d[key]!
}
}
Now we can write the last fetch like this:
let result4 = my["b.x"].val
You can readily see that if this were a chain of five or ten nodes, that at least would constitute a considerable notational savings:
let my = Thing("n")
let b = Thing("b1")
let x = Thing("x2")
let y = Thing("y3")
let z = Thing("z4")
y.d["z"] = z
x.d["y"] = y
b.d["x"] = x
my.d["b"] = b
let result = my["b.x.y.z"].val // better than nothing...
Okay - but having done that, I can eliminate the unwanted .val
at the end of every fetch, and thus accomplish something like what you originally asked to accomplish!
class Thing {
var val : String
var d = [String:Thing]()
init(_ val:String) {self.val = val}
subscript(key:String) -> String {
let path = split(key, {$0=="."}, maxSplit: 1)
if path.count == 2 {
return self.d[path[0]]![path[1]]
}
return self.d[key]!.val
}
}
let my = Thing("n")
let b = Thing("b1")
let x = Thing("x2")
let y = Thing("y3")
let z = Thing("z4")
y.d["z"] = z
x.d["y"] = y
b.d["x"] = x
my.d["b"] = b
let result1 = my["b"]
let result2 = my["b.x.y.z"]
Your original question, to be sure, was about setting, not getting. You could do something similar with the subscript setter, but I leave this to you to work out the details, as the original question was not formulated in a way that allows me understand what the exact spec would be.