Swift中功能性的Lazily实例化路径

时间:2015-02-22 01:01:41

标签: swift functional-programming lazy-initialization

我想要一种方法来轻松实例化Swift中的“路径”或一系列字典。例如,假设我有一个类存储的东西(略微夸张):

class aClass<T: Hashable, U> {
  var paths:[T:[T:[T:[U]]]] = [:]
}

我们有三个单独的DictsArray结尾。我有一些函数需要在数组中存储类型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) }
}

我遇到的问题是DictArray都是通过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多行代码要好得多,否则我将不得不写。

更新2

工作。它似乎有效,但我最终遇到了与之前相同的问题:DictArray值通过中缀函数复制。因此,对于转换的每个“阶段”,我正在修改副本而不是原始副本。问题是似乎无法通过函数的引用 out 传递值。您只能通过 中的参考值将值传递给函数(使用inout)。

0 个答案:

没有答案