tachyonics
(Simon Pilkington)
1
At the moment it doesn't look like it is possible to use functional decomposition with Result Builders. For example with this code
@CodeBlockItemListBuilder func statements() -> ExpressibleAsCodeBlockItemList {
ImportDecl(path: "Foundation")
ClassDecl(classOrActorKeyword: .class, identifier: "SomeViewController", membersBuilder: {
VariableDecl(.let, name: "tableView", type: "UITableView")
})
}
it seems reasonable that the following should be equivalent
@CodeBlockItemListBuilder func statements() -> ExpressibleAsCodeBlockItemList {
ImportDecl(path: "Foundation")
moreStatements()
}
@CodeBlockItemListBuilder func moreStatements() -> ExpressibleAsCodeBlockItemList {
ClassDecl(classOrActorKeyword: .class, identifier: "SomeViewController", membersBuilder: {
VariableDecl(.let, name: "tableView", type: "UITableView")
})
}
Am I missing something here?
1 Like
jrose
(Jordan Rose)
2
You've changed the type: moreStatements returns ExpressibleAsCodeBlockItemList, which isn't a single element of CodeBlockItemList. By analogy, your first example has:
let elements = [ImportDecl(…), ClassDecl(…)]
and your second example has
let extracted = [ClassDecl(…)]
let elements = [ImportDecl(), extracted] // extra level of nesting
You can explicitly have your builder do flattening, or you can have your extracted function return a single code block item instead of a list.
1 Like
tachyonics
(Simon Pilkington)
3
So for clarity and prosperity, adding another buildExpression override to the builder will allow this to work-
/// Provide the ability to an expression that returns an `ExpressibleAsCodeBlockItemList`
/// such as another @CodeBlockItemListBuilder
public static func buildExpression(_ expression: ExpressibleAsCodeBlockItemList) -> Component {
let codeBlockItemList = expression.createCodeBlockItemList()
return codeBlockItemList.elements
}
Makes sense, although not particularly obvious.
2 Likes