I have a function that takes a reference to an array as an argument. It is callred recursively.
I find that the second time that the function is called, it seems to handle the parameter as a normal value type, copying it and not passing it by reference.
In the code below, I call createDataPoints with "A.B.C" as argument. It should create a data point named "A" and call addDataPoint with "B.C" as argument. This should add "B" as a child data point to "A" and call it with "C" as argument.
If I step through the code, it does all of this, and it seems to work correctly. But my original array, dataPoints only contains the result of the first call to addDataPoint(), which is "A" and it has zero children.
From what I can tell, it works correctly when addDataPoint() is called for the firt time at line 44, but not when it is called when it is called recursively at line 37.
What am I missing? I am expecting dataPoints (created line 48) to contain one item with name "A" which contains one child called "B" which contains a child called "C" after createDataPoints() line 49 has returned.
[ Paste the code below in a playground, or a command line app to step through it ]
import Foundation
struct DataPointInfo {
var name: String
var children = [DataPointInfo]()
init(name: String) {
self.name = name
}
}
extension Array where Element == DataPointInfo {
func dataPointWithName<T:StringProtocol>(name: T) -> DataPointInfo? {
for dataPoint in self {
if dataPoint.name == name {
return dataPoint
}
}
return nil
}
}
let name1 = "A.B.C"
let name2 = "A.B.D"
let name3 = "A.Last"
let names = [name1] // ,name2, name3]
func addDataPoint(parentLevel: inout [DataPointInfo], parts: [Substring]) {
if parts.count == 1 {
parentLevel.append(DataPointInfo(name: String(parts[0])))
} else {
var parent = parentLevel.dataPointWithName(name: parts[0])
if (parent == nil) {
parent = DataPointInfo(name: String(parts[0]))
parentLevel.append(parent!)
}
addDataPoint(parentLevel: &parent!.children, parts: Array(parts.suffix(from: 1)))
}
}
func createDataPoints(names: [String]) {
for name in names {
let parts = name.split(separator: ".")
addDataPoint(parentLevel: &dataPoints, parts: parts)
}
}
var dataPoints = [DataPointInfo]()
createDataPoints(names: names)