I am trying to use @resultBuilder, however I have run into an issue while trying to support for loops
Problem:
I get the following compilation error at the line of of the for loop: error: ResultBuilder.playground:29:5: error: cannot pass array of type '[String]' as variadic arguments of type 'String'
Xcode's auto-completion Signature of buildArray
Using Xcode's auto-completion the buildArray's signature is as follows
The Component in your builder is not String, it's actually [String], so the buildBlock should actually accept components: [String]..., and to translate a single String you need buildExpression.
In so far, String can only potentially support the result from buildExpression. If you'd like to use [String] for other results, you should use [String] (or enum if you want single-String to remain single).
That said, it's possible to support multiple Component type, which may be useful to restrict the order of the component appearances.
func buildBlock(_: Header, _: Body, _: Footer) -> FinalResult { ... }
...
// You need to do
{
Header
Body
Footer
}
Though I don't think it's very useful in this case.
Still learning this, based on my crude understanding (I could be wrong), the value returned by buildArray needs to be Component type. Component is defined by buildBlock
Personally, I wouldn't use the term Component as though each builder has exactly one. It's quite possible to have many (looking at you, ViewBuilder).
In any case, if you have: buildArray(_: [C1]) -> C2, you'd need at least:
buildBlock(...) -> C1, for block inside for-loop,
buildBlock(..., _: C2, ...) -> C3 for block containing for-loop.
And it's far easier if C1, C2, and C3 are all [String], which would be your "Component" type. In that case, you can also just use buildBlock(_: [String]...) -> [String] for both buildBlock.
then the entire for loop would be rendered down to a single String, which is not necessarily what you'd want. In general I would advise to initially design builders with a single Component in mind, and think about how to support it in all builders functions, adding buildExpressions when some specific expression must be resolved into a Component instance. Then you can expand the definition of Component as @Lantua mentioned, if you need special behavior, like specific ordering of elements in the builder function, or different behavior based of which "components" are merged in buildBlock.