6

I'm trying to wrap my head around @_functionBuilder. There is one case I haven't been able to figure out.

I put together this simple example, when there are two passengers this works great. But when there is only 1 I get this error:

error: FunctionBuilder.playground:21:5: error: cannot convert value of type 'Passanger' to closure result type '[Passanger]'

@_functionBuilder
struct PassangerBuilder {
    static func buildBlock(_ passangers: Passanger...) -> [Passanger] {
        return passangers
    }
}

struct Passanger {
    let name: String
}

struct Car {
    let passangers: [Passanger]

    init(@PassangerBuilder _ builder: () -> [Passanger]) {
        self.passangers = builder()
    }
}

Car {
    Passanger(name: "Tom")
//    Passanger(name: "Mary")
}
keegan3d
  • 10,357
  • 9
  • 53
  • 77

2 Answers2

7

My solution is add more init function with single item Passanger return to struct Car. It will be:

struct Car {
    let passangers: [Passanger]

    init(@PassangerBuilder _ builder: () -> [Passanger]) {
        self.passangers = builder()
    }

    init(@PassangerBuilder _ builder: () -> Passanger) {
        self.passangers = [builder()]
    }
}

Hope to help you

Thanh Vu
  • 1,599
  • 10
  • 14
  • That worked thanks, still hoping to find a more generic solution – keegan3d Aug 18 '19 at 14:32
  • 1
    This workaround probably isn't doing what you expect. The `@PassangerBuilder` can be omitted from the second `init` and the code produced is the same as the function builder is being ignored. There appears to be a "feature" in the compiler/language design, see [Function Builder not working when only one value?](https://stackoverflow.com/questions/58409839/function-builder-not-working-when-only-one-value) – CRD Oct 16 '19 at 22:48
1

For anyone else that ends up here.

As I answered on the question referenced by CRD, there is a bug on the current implementation of function builders where it ignores the function builder when there is only one value available. It's fixed on Swift 5.3 and available on Xcode 12.

Thanh Vu's solution of making a overload works for now, but you don't even need the @PassangerBuilder annotation.

Robuske
  • 198
  • 1
  • 8