SE-0289: Function Builders

  • What is your evaluation of the proposal?

-0.5. The feature is dramatically overpowered for the majority of use cases. This in itself is not a problem, but it should coincide with standard library additions that allow for the feature to be used succinctly for the most common cases. This is covered under "Future Directions", but it should be part of the proposal itself.

I believe adopting the proposal as currently described will result in a lot of people writing code that looks like this, as is already ubiquitous in projects linked in the Awesome Function Builders repository:

@_functionBuilder
public struct NodeBuilder {
    public static func buildBlock(_ components: Node...) -> Node {
        .fragment(components)
    }

    public static func buildIf(_ component: Node?) -> Node {
        component ?? []
    }

    public static func buildEither(first: Node) -> Node {
        first
    }

    public static func buildEither(second: Node) -> Node {
        second
    }
}

This is bad code. Forcing people to redefine obvious monoid operations should give one pause. Even the fact that buildBlock wraps the components in ".fragment(_:)" is misleading: what is being built is not an HTML Node, it is an array of HTML Nodes to be added as children to the node created by the calling function. Defining unnecessary weird tree structures is another symptom of functionbuilders as they currently exist.

Most people just want ArrayBuilder. Adopting the proposal without it will make users define countless redundant unspecialized functionbuilders and then despair to remove them once the feature they actually want is made available. The proposal says this could be added with "more experience" but I don't know why more experience is needed when the demand for a much simpler feature set is already apparent.

15 Likes