3

I have a functionBuilder

@_functionBuilder
struct MyBuilder {
    static func buildBlock(_ numbers: Int...) -> Int {
        var result = 0
        for number in numbers {
            result += number * 2
        }
        return result
    }
}

Function

func myFunc(@MyBuilder builder: () -> Int) -> Int {
    builder()
}

use

let a = myFunc {
    10
    20
}
print(a) // print 60 is work!

but

let b = myFunc {
    10
}
print(b) // print 10?

Why is b not 20?

I try add other buildBlock

static func buildBlock(number: Int) -> Int {
    return number * 2
}

But not working :(

Any idea?

aiur
  • 649
  • 2
  • 7
  • 21
  • Interesting question, I tried to make it work, but I failed either:) In fact, you can change your implementation of `buildBlock` to one line: `numbers.reduce(0, { $0 + $1 * 2 })`. – Michcio Oct 16 '19 at 10:46

2 Answers2

3

Any idea?

What is happening in the failing case is that { 10 } is being treated as a closure of type () -> Int directly and the compiler doesn't appear to consider the function builder at all. The code that is produced is simply a function which returns 10.

This appears to a "feature" where the recognition of { 10 } as a simple closure overrides its possible recognition as a use of the function builder. This may just be a compiler issue or worse it might be a language definition problem...

Please head to feedbackassistant.apple.com and file a report.

CRD
  • 52,522
  • 5
  • 70
  • 86
2

The accepted answer is correct, it is just passing the value and ignoring the builder.

But it's a bug, not a feature.

It's fixed on Swift 5.3, which is only available on Xcode 12 (currently in beta).

Robuske
  • 198
  • 1
  • 8