关于@resultBuilder中buildBlock的参数类型和return类型的问题
A question about parameter type and return type of buildBlock in @resultBuilder
根据swift 语言指南,我需要在定义结果生成器时实现buildBlock 方法。指南还说:
”
static func buildBlock(_ components: Component...) -> Component
将一组部分结果合并为一个部分结果。结果生成器必须实现此方法。
“
很明显,参数类型和return类型应该是一样的。但是,如果我使用不同的类型,它似乎也没有问题。我在下面写了一些简单的代码:
@resultBuilder
struct DoubleBuilder {
static func buildBlock(_ components: Int) -> Double {
3
}
}
在Xcode编译成功。类型可以不一样吗?好像和官方指导不一致
编辑:
SwiftUI中ViewBuilder中buildBlock方法的参数类型也与return类型不同。
例如:
static func buildBlock(C0, C1) -> TupleView<(C0, C1)>
当他们说
static func buildBlock(_ components: Component...) -> Component
他们并不严格地表示存在一种类型,Component
,buildBlock
和return必须接受。它们只是意味着 buildBlock
应该接受一些参数,其类型是“部分结果”的类型,而 return 一个类型是“部分结果”的类型。将它们都称为 Component
可能有点令人困惑。
我认为 Swift evolution proposal 解释得更好一些(强调我的):
The typing here is subtle, as it often is in macro-like features. In the following descriptions, Expression
stands for any type that is acceptable for an expression-statement to have (that is, a raw partial result), Component
stands for any type that is acceptable for a partial or combined result to have, and FinalResult
stands for any type that is acceptable to be ultimately returned by the transformed function.
因此 Component
、Expression
和 FinalResult
等不必固定为单一类型。您甚至可以重载 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
的闭包参数需要 return 类型的值 Double
。最后两个是因为结果构建器的转换试图调用 MyBuilder.buildBlock(10, 20)
.
如果您查看转换后的闭包,一切都有意义:
foo {
let v1 = 10
let v2 = 20
return MyBuilder.buildBlock(v1, v2)
}
本质上只要转换后的代码通过编译就没有问题
根据swift 语言指南,我需要在定义结果生成器时实现buildBlock 方法。指南还说:
” static func buildBlock(_ components: Component...) -> Component
将一组部分结果合并为一个部分结果。结果生成器必须实现此方法。 “
很明显,参数类型和return类型应该是一样的。但是,如果我使用不同的类型,它似乎也没有问题。我在下面写了一些简单的代码:
@resultBuilder
struct DoubleBuilder {
static func buildBlock(_ components: Int) -> Double {
3
}
}
在Xcode编译成功。类型可以不一样吗?好像和官方指导不一致
编辑:
SwiftUI中ViewBuilder中buildBlock方法的参数类型也与return类型不同。 例如:
static func buildBlock
当他们说
static func buildBlock(_ components: Component...) -> Component
他们并不严格地表示存在一种类型,Component
,buildBlock
和return必须接受。它们只是意味着 buildBlock
应该接受一些参数,其类型是“部分结果”的类型,而 return 一个类型是“部分结果”的类型。将它们都称为 Component
可能有点令人困惑。
我认为 Swift evolution proposal 解释得更好一些(强调我的):
The typing here is subtle, as it often is in macro-like features. In the following descriptions,
Expression
stands for any type that is acceptable for an expression-statement to have (that is, a raw partial result),Component
stands for any type that is acceptable for a partial or combined result to have, andFinalResult
stands for any type that is acceptable to be ultimately returned by the transformed function.
因此 Component
、Expression
和 FinalResult
等不必固定为单一类型。您甚至可以重载 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
的闭包参数需要 return 类型的值 Double
。最后两个是因为结果构建器的转换试图调用 MyBuilder.buildBlock(10, 20)
.
如果您查看转换后的闭包,一切都有意义:
foo {
let v1 = 10
let v2 = 20
return MyBuilder.buildBlock(v1, v2)
}
本质上只要转换后的代码通过编译就没有问题