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

时间:2018-01-14 23:51:02

标签: swift types

我一直在研究Exercism.io的Swift轨道,在将我的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 ]() } }
}

我的重点是var s dataleftright。看看它们几乎是如何吐出彼此的图像?不是应该完成,而是可以完成:编写一个函数,通过一个参数接受TBST,通过另一个参数接受元组位置({{1} }),并返回一个枚举分解的函数或闭包,并返回传入类型的捕获值?

我意识到我的代码的短名称和单行代码远远超过了愚蠢的地步。经过对这个初始解决方案的几次迭代后出现了,我认为你会同意它更具可读性,尽管模式不太明显:

Int

1 个答案:

答案 0 :(得分:1)

这绝对可以简化,也可能应该是辅助功能:

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 }

我在枚举上构建了这些类型的帮助程序,以便始终将关联数据转换为Optionals(在某些情况下作为公共方法)。

这也可以在allData中使用,我可能会用这种方式编写(链式+因在Swift中创建编译问题而臭名昭着,并且由于创建中间副本):

func allData() -> [ T ] {
    if let (v, l, r) = vlr {
        var result = l.allData()
        result.append(v)
        result.append(contentsOf: r.allData())
        return result
    }
    return []
}