//----------------------------------------------------- Given the following data structure:
struct Leaf{
// data members
}
struct Branch{
// data members, including a list of leaves
}
struct Trunk{
// data members, including a list of branches
}
//----------------------------------------------------- Is it possible to write these functions? :
func findAbsoluteKeypathsToDoubles(beginning at: Trunk) -> [WritableKeyPath<Trunk, Double>]
{
// does a BFS or DFS search and returns, for example
// (if the tree structure had only one branch and two leaves):
// [\Trunk.diameter, \Trunk.branches[0].length, \Trunk.branches[0].leaves[0].surfaceArea, \Trunk.branches[0].leaves[1].surfaceArea]
}
func findAbsoluteKeypathsToDoubles(withMemberName: [String], beginning at: Trunk) -> [WritableKeyPath<Trunk, Double>]
{
// does a search and returns, if withMemberName were ["diameter", "length"] :
// (again, if the tree structure had only one branch and two leaves)
// [\Trunk.diameter, \Trunk.branches[0].length] // no surfaceArea here
}
The main issues I seem to be hitting are when I have to know the root and value types of a keypath to use it, I can't just use it.
For example, if I want to keep track of the frontier during BFS, I would like to represent it as [KeyPath], but it must be explicitly [KeyPath<Root, Value>], which makes it rigid and hard to use at different depths of BFS
I realize my problem has something to do with how Swift needs to know the types of all keypaths at compile time for keypaths to have the type-safe features they do, and I'm not sure if the "dynamicism" I want is even possible. Is there an approach that achieves it while still letting Swift be type-safe with keypaths?
Am I asking too much of keypaths?
//----------------------------------------------------- Ideas I've tried:
// -- Make each struct hold a list of keypaths (one for each of its members) for use during BFS - still not sure if this is is possible, but no luck so far
// -- Recursive DFS search - ran into issues when I wanted to use a KeyPath, but had to know its exact root and value types in order to use it, and didn't know how to properly genericize the recursive function
Joe_Groff
(Joe Groff)
2
You can use PartialKeyPath<Root>, which is a superclass of KeyPath<Root, *>, to represent a heterogeneous set of key paths with the same root.
Thanks Joe
I've been familiar with the concept of the PartialKeyPath for a while, although I guess keypaths are enough of a new concept for me that I don't immediately see how PartialKeyPath solves the problem.
It seems like you mean to say that using PartialKeyPath solves the problem of representing the frontier of a BFS, is that true?
I've tried to incorporate PartialKeyPath<Trunk> into findAbsoluteKeypathsToDoubles, but I've found another issue:
When I try to use a PartialKeyPath from the frontier to get a list of children on the next level, I can't because the compiler doesn't seem to know that that keypath will in fact give a list. For example, on the first level of BFS I need to use \Trunk.branches to get the list of Branches, but I get an "Any has no subscript members" error when I try to subscript the resulting list of branches. The compiler doesn't know it's an Array, and won't let me use it as one. Casting to an Array hasn't worked...