关于@resultBuilder中buildBlock的参数类型和返回类型的问题



根据swift语言指南,我需要在定义结果构建器时实现buildBlock方法。指南还说:

"静态函数buildBlock(_ components: Component…)>组件

将部分结果数组合并为单个部分结果。结果构建器必须实现此方法。">

显然,形参类型和返回类型应该相同。但是,如果我使用不同的类型,似乎也没有问题。我在下面写了一些简单的代码:

@resultBuilder
struct DoubleBuilder {
static func buildBlock(_ components: Int) -> Double {
3
}
}

在Xcode中编译成功。类型可以不同吗?这似乎与官方指南不一致。

编辑:

SwiftUI中ViewBuilder中buildBlock方法的参数类型也与返回类型不同。例如:

static function buildBlock<C0,>(C0, C1) ->TupleView<(C0, C1)在

当他们说

static func buildBlock(_ components: Component...) -> Component

它们不严格地意味着存在一种类型Component,buildBlock必须接收并返回。它们只是表示buildBlock应该接受一些参数,这些参数的类型是"部分结果"的类型,并返回一个"部分结果"的类型。将它们都称为Component可能会有点混乱。

我认为Swift进化方案解释得更好一点(强调我的):

这里的输入是微妙的,就像它经常出现在类似宏的特性中一样。在下面的描述中,Expression代表any表达式语句可以接受的类型(即原始的部分结果),Component表示any类型可以被部分或组合结果接受,FinalResult表示any转换后的函数最终返回的可接受的类型。

因此Component,ExpressionFinalResult等不必固定为单一类型。您甚至可以重载buildXXX方法,正如稍后在演进建议中所演示的那样。

最终,当您实际使用时,结果构建器将转换为对buildXXX

的调用。这时,如果有输入错误,就会报告。 例如,

@resultBuilder
struct MyBuilder {
static func buildBlock(_ p1: String, _ p2: String) -> Int {
1
}
}
func foo(@MyBuilder _ block: () -> Double) -> Double {
block()
}
foo { // Cannot convert value of type 'Int' to closure result type 'Double'
10 // Cannot convert value of type 'Int' to expected argument type 'String'
20 // Cannot convert value of type 'Int' to expected argument type 'String'
}

第一个错误是因为结果生成器的结果类型是Int,但是foo的闭包参数期望返回类型是Double。最后两个原因是因为结果构建器的转换试图调用MyBuilder.buildBlock(10, 20)

如果你看一下转换后的闭包,这一切都是有意义的:

foo {
let v1 = 10
let v2 = 20
return MyBuilder.buildBlock(v1, v2)
}

基本上,只要转换后的代码可以编译,就没有问题。

在这里查看更多关于转换的详细信息。

最新更新