我想要一种方法来轻松实例化Swift中的“路径”或一系列字典。例如,假设我有一个类存储的东西(略微夸张):
class aClass<T: Hashable, U> {
var paths:[T:[T:[T:[U]]]] = [:]
}
我们有三个单独的Dicts
以Array
结尾。我有一些函数需要在数组中存储类型U
:
func store(path:(first:T,second:T,third:T), object:U)
如果没有某种嵌套的地狱金字塔,你会如何实现这一点?理想情况下,如果我访问它并且没有Dict
可用,我希望能够在路径中设置一个空的Dict
“动态”。与“leaf”数组相同。
我想我希望的是某种infix
运算符(s?)允许我做这样的事情(假设为infix:?>
,>>
) :
func store(path:(first:T,second:T,third:T), object:U) {
paths[path.first] ?> [:] >> path.second ?> [:] >> path.third ?> []
paths[path.first]?[path.second]?[path.third].append(object)
}
或者,更好的是:
func store(path:(first:T,second:T,third:T), object:U) {
paths[path.first] ?> [:] >> path.second ?> [:] >> path.third ?> [] >>> { u in u.append(object) }
}
我遇到的问题是Dict
和Array
都是通过Swift中的值传递的。这迫使我进行一些严格的嵌套,以便正确设置“路径”,这样我就可以插入一个叶子对象。
我可能会问太多Swift,但作为一种半功能语言,我一直认为必须有一种更简单的方法来实现这一目标。
我真的非常非常接近:
infix operator ?> { associativity left }
private func ?> <U,T>(var v:(d:[T:U], v:T), var r:U) -> U {
if let dv = v.d[v.v] {
return dv
} else {
v.d.updateValue(r, forKey: v.v)
return r
}
}
infix operator >< { associativity left }
private func >< <T,U>(t:T, u:U) -> (T,U) {
return (t, u)
}
infix operator >>> { associativity left }
func >>> <T> (var v:T, f:(T -> ())) {
f(v)
}
从这里我应该能够做到这样的事情:
paths >< path.first ?> [:] >< path.second ?> [:] >< path.third ?> [] >>> { arr in arr.append(object) }
这几乎有效。我得到的唯一错误是:
类型'[T]'的不可变值只有名为'append'的变异成员
我似乎无法在运算符中指定我需要传入的字典是可变的。有什么想法吗?
我也承认infix
运算符会使代码模糊不清。但即便如此,我认为它比维护嵌套所需的20多行代码要好得多,否则我将不得不写。
它不工作。它似乎有效,但我最终遇到了与之前相同的问题:Dict
和Array
值通过中缀函数复制。因此,对于转换的每个“阶段”,我正在修改副本而不是原始副本。问题是似乎无法通过函数的引用 out 传递值。您只能通过 中的参考值将值传递给函数(使用inout
)。