5

Now that @autoclosure is part of the parameter declaration as opposed to type, how does one declare that a function takes a variadic amount of autoclosures?

Before:

public func coalesce<T>(all : @autoclosure () -> T? ...) -> T? {
    for f : () -> T? in all {
        if let x = f() { return x }
    }
    return nil
}

After: ???

Nathan Kot
  • 2,392
  • 1
  • 21
  • 31
  • For what it's worth, there was apparently a work-around possible for a previous version of Swift, but it doesn't work with Swift 3. https://gist.github.com/kasrak/2b79c458713cf77db632 – RenniePet Dec 13 '16 at 06:54

2 Answers2

7

I opened rdar://19782845, "Swift 1.2: Variadic auto-closures no longer supported," and was given the following response from Apple Developer Relations:

This issue behaves as intended based on the following:

@autoclosure is only allowed on parameters of function type, and varargs is an array. This is not expected to work.

stephencelis
  • 4,954
  • 2
  • 29
  • 22
  • 2
    Remotely related: you can't pass functions taking autoclosure parameters (such as the short-circuiting operators `||`, `&&`) to another function anymore, see http://stackoverflow.com/a/28648376/1187415 and the following discussion. – Martin R Apr 20 '15 at 14:25
  • @MartinR Is that still the case? What about `@autoclosure(escaping)`? (See the release notes here: https://developer.apple.com/library/ios/releasenotes/DeveloperTools/RN-Xcode/Chapters/Introduction.html) – stephencelis Apr 20 '15 at 14:35
  • @stephencelis: I tried various combinations and wasn't able to make it compile. The problem is that not the function parameter itself should be marked autoclosure, but the function parameter is itself a function taking an autoclosure parameter. – Martin R Apr 20 '15 at 14:39
  • @MartinR Ah, right, I misunderstood and thought you meant passing `@autoclosure` parameters directly, which is only possible using `(escaping)`. – stephencelis Apr 20 '15 at 14:41
0

You can wrap your parameters to a type that takes @autoclosure on its initialization e.g.:

public struct Arg<T> {
    let f: () -> T?

    init(_ f: @escaping @autoclosure () -> T?) {
        self.f = f
    }
}

public func coalesce<T>(all: Arg<T>...) -> T? {
    for i in all {
        if let x = i.f() { return x }
    }
    return nil
}

let a = 2
let c = coalesce(all: Arg(nil), Arg(a * 3), Arg(100)) // 6
iUrii
  • 11,742
  • 1
  • 33
  • 48