【发布时间】:2018-06-23 15:10:47
【问题描述】:
我一直在研究 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 ]() } }
}
我的重点是 vars data、left 和 right。看看他们是如何几乎吐出彼此的照片的?并不是说它应该完成,而是可以完成:编写一个函数,通过一个参数接受T 或BST,通过另一个参数(Int) 接受一个元组位置,并返回一个枚举分解并返回传入类型的捕获值的函数或闭包?
我意识到我的代码的短名称和单行性远远超出了愚蠢的程度。它是在对这个初始解决方案进行几次迭代后出现的,我想你会同意它更具可读性,尽管模式不太明显:
indirect enum BinarySearchTree< T: Comparable> {
case Node( T, BinarySearchTree, BinarySearchTree )
case None
init( _ value: T ) { self = .Node( value, .None, .None ) }
mutating func insert( _ new: T ) {
if case .Node( let value, var left, var right ) = self {
if new <= value { left.insert( new ) }
else { right.insert( new ) }
self = .Node( value, left, right )
} else { self = .Node( new, .None, .None ) }
}
var data: T? {
if case let .Node( value, _, _ ) = self { return value }
else { return nil }
}
func allData() -> [ T ] {
if case let .Node( value, left, right ) = self {
return left.allData() + [ value ] as [ T ] + right.allData()
} else { return [ T ]() }
}
var left: BinarySearchTree? {
if case let .Node( _, left, _ ) = self { return left }
else { return nil }
}
var right: BinarySearchTree? {
if case let .Node( _, _, right ) = self { return right }
else { return nil }
}
}
【问题讨论】: