我不会使用结果构建器,而是只需编写如下函数:
func buildArray<T>(_ type: T.Type = T.self, block: (inout [T]) -> Void) -> [T] {
var array = [T]()
block(&array)
return array
}
用途:
let array = buildArray(Int.self) {
$0.append(1)
$0.append(2)
$0.append(3)
// you can put whatever control flow statements you need in here...
}
如果你真的讨厌一直写$0.append
,你可以使用结果构建器:
@resultBuilder
struct ArrayBuilder<T> {
typealias Component = [T]
static func buildExpression(_ expression: T) -> Component {
[expression]
}
static func buildBlock(_ components: Component...) -> Component {
components.flatMap { $0 }
}
static func buildArray(_ components: [Component]) -> Component {
components.flatMap { $0 }
}
static func buildOptional(_ component: Component?) -> Component {
component ?? []
}
static func buildEither(first component: Component) -> Component {
component
}
static func buildEither(second component: Component) -> Component {
component
}
}
请注意,这会将闭包中的所有表达式转换为单元素array.然后将它们连接在一起.我没有对此进行基准测试,但我怀疑这会导致相当多的数组分配.如果这是一个问题,您可以try 另一个实现:
@resultBuilder
struct ArrayBuilder<T> {
enum Component {
case array([T]), element(T), nothing
}
static func buildExpression(_ expression: T) -> Component {
.element(expression)
}
static func buildBlock(_ components: Component...) -> Component {
buildArray(components)
}
static func buildArray(_ components: [Component]) -> Component {
var array = [T]()
for component in components {
switch component {
case .array(let a): array.append(contentsOf: a)
case .element(let t): array.append(t)
default: break
}
}
return .array(array)
}
static func buildOptional(_ component: Component?) -> Component {
component ?? .nothing
}
static func buildEither(first component: Component) -> Component {
component
}
static func buildEither(second component: Component) -> Component {
component
}
static func buildFinalResult(_ component: Component) -> [T] {
switch component {
case .array(let a): return a
case .element(let t): return [t]
default: return []
}
}
}
这对Component
类型使用了枚举,因此闭包中的表达式可以改为.element(expr)
,从而避免了一些数组分配.
然后,buildArray
函数可以如下所示:
func buildArray<T>(_ type: T.Type = T.self, @ArrayBuilder<T> block: () -> [T]) -> [T] {
block()
}
与前buildArray
个不同,SWIFT通常能够根据构建器中的表达式推断数组的类型:
let array = buildArray {
1
2
3
// you can use if, switch, and for statements in here
}