I can certainly understand the desire to have a simpler way to declare new function builders, particularly simple ones only aggregate values and don't need to propagate types the way more advanced builders like SwiftUI's ViewBuilder
do. However, I don't think that it makes sense to approach this as two different APIs from the language perspective. Rather, we should try to make the feature we have composable enough to enable the simple interface. I think we're almost there (more on that in a moment), but first I want to disagree with this bit:
Philosophically, function builders are intended to be more declarative in nature, similar to what fits well if the entire closure were a single expression. Arbitrary control-flow (like break
, continue
, etc.) goes against that philosophy. There us a short paragraph about this in future directions, but I sorta feel like it's not a good direction. And I certainly don't think we should do it for "high-level" function builders and not "low-level" ones.
Back to making the simple case simple. @anreitersimon showed an example that introduces a FunctionBuilderProtocol
that opts in to all of the syntax that a function builder can support, wrapping it up in default implementations so a client can define a new, fully-featured function builder by only implementing buildFinalResult
. I think your "Builder" example can be layered on top of that fairly easily.
Note that @anreitersimon's example doesn't work today because of an oversight in the way we did name lookup for the build
functions. I just put up a bug fix to the function builders implementation that makes it work. I've also added this example to the proposal so others can find it more easily.
Perhaps some form of that protocol belongs in the standard library. That would address one of @davedelong's concerns as well:
@JoeyKL notes that having such a facility would cover a lot of use cases:
That we can define this as our own protocol on top of the existing proposal indicates that the language itself doesn't need another "simpler" mode. Rather, we can point people at this protocol (or something like it) as the way to eliminate boilerplate for a class of use cases.
Doug
[EDIT: Added link to the new discussion in the proposal of a "simple" function builder protocol, and response to @JoeyKL's comment that came in a moment after my original post.]