Swift 将类型传递给函数以返回返回该类型的闭包?

Swift 将类型传递给函数以返回返回该类型的闭包?,swift,types,Swift,Types,我一直在研究Exercism.io的Swift track,在将我针对BinarySearchTree问题的解决方案重构为小型代码后,我注意到一个似乎可以重构的模式。我想答案是“不,你不能那样做”,但我觉得这是值得问的 typealias BinarySearchTree = BST indirect enum BST< T: Comparable> { case N( T, BST, BST ) case E init( _ v: T ) { self

我一直在研究Exercism.io的Swift track,在将我针对BinarySearchTree问题的解决方案重构为小型代码后,我注意到一个似乎可以重构的模式。我想答案是“不,你不能那样做”,但我觉得这是值得问的

typealias BinarySearchTree = BST

indirect enum BST< T: Comparable> {
    case N( T, BST, BST )
    case E

    init( _ v: T ) { self = .N( v, .E, .E ) }

    mutating func insert( _ n: T ) {
        if case .N( let v, var l, var r ) = self {
            if n <= v { l.insert( n ) } else { r.insert( n ) }
            self = .N( v, l, r )
        } else { self = .N( n, .E, .E ) }
    }

    var  data:    T?        { if case let .N( v, _, _ ) = self { return v } else { return nil } }
    var  left:    BST?      { if case let .N( _, l, _ ) = self { return l } else { return nil } }
    var  right:   BST?      { if case let .N( _, _, r ) = self { return r } else { return nil } }

    func allData() -> [ T ] { if case let .N( v, l, r ) = self { return l.allData() + [ v ] as [ T ] + r.allData() } else { return [ T ]() } }
}

这完全可以通过一个助手函数来简化,而且可能应该简化:

private var vlr: (T, BST, BST)? {
    switch self {
    case let .N(v, l, r): return (v,l,r)
    case .E: return nil
    }
}

var  data:  T?   { return vlr?.0 }
var  left:  BST? { return vlr?.1 }
var  right: BST? { return vlr?.2 }
我在枚举上构建了这些类型的帮助器,以便始终将相关数据转换为可选数据(在某些情况下,作为公共方法)

这也可以用于
allData
,我可能会这样写(chained
+
因在Swift中产生编译问题而臭名昭著,并且由于创建中间副本,运行时效率极低):


令人惊叹的!我想这是一个太接近问题的例子。我看不到过去的类型,意识到我可以将它们全部返回,然后从一个元组中选择我需要的。谢谢我讨厌看到重复的代码可以像你展示的那样封装。在
allData()
中链接的
+
上,我知道您提到的性能问题。我想这就是为什么我需要将
[value]转换为[T]
,它才能工作的原因。我有一个稍微不那么简洁的版本,在一次迭代中使用了
.append()
,直到我把它转换成链接的
+
版本。是的,我不知道为什么
+
需要
as[t]
。这是所有疯狂的
+
重载的奇怪副作用。
private var vlr: (T, BST, BST)? {
    switch self {
    case let .N(v, l, r): return (v,l,r)
    case .E: return nil
    }
}

var  data:  T?   { return vlr?.0 }
var  left:  BST? { return vlr?.1 }
var  right: BST? { return vlr?.2 }
func allData() -> [ T ] {
    if let (v, l, r) = vlr {
        var result = l.allData()
        result.append(v)
        result.append(contentsOf: r.allData())
        return result
    }
    return []
}