I have a function that uses @autoclosure. Is there a way to make @autoclosure behave similarly to overloaded functions, so it automatically knows which syntax is right for variables like in my case?
func myEnvironment(_ bindings: @autoclosure () -> [Int], _ body: ([Int]) -> Int) -> Int {
let vars = bindings()
return body(vars)
}
// prints 4
let result = myEnvironment([]) { _ in
2 + 2
}
// Error
// prints 6
let result2 = myEnvironment {
let x = 1
let y = 2
let z = 3
return [x, y, z]
} _: { vars in
vars[0] + vars[1] + vars[2]
}
Error
// prints 6
let result2 = myEnvironment {
let x = 1
let y = 2
let z = 3
return [x, y, z]
} _: { vars in
vars[0] + vars[1] + vars[2]
}
error 1:
Contextual type for closure argument list expects 1 argument, which cannot be implicitly ignored
error 2:
Cannot convert value of type '[Int]' to closure result type 'Int'
Is there a way to achieve the desired behavior, or do I need to modify my code?
I saw this post How to use Swift @autoclosure but it did not answer my question. Any suggestions are appreciated.
I assume you want to also allow the caller to pass in a code block that contains multiple lines of code as the autoclosure.
You can declare another overload that does not take an @autoclosure
.
// The '@autolcosure' overload can delegate to the new overload:
func myEnvironment(_ bindings: @autoclosure () -> [Int], _ body: ([Int]) -> Int) -> Int {
myEnvironment(bindings, body)
}
func myEnvironment(_ bindings: () -> [Int], _ body: ([Int]) -> Int) -> Int {
let vars = bindings()
return body(vars)
}
// ------------
// or the other way around!
func myEnvironment(_ bindings: () -> [Int], _ body: ([Int]) -> Int) -> Int {
myEnvironment(bindings(), body)
}
func myEnvironment(_ bindings: @autoclosure () -> [Int], _ body: ([Int]) -> Int) -> Int {
let vars = bindings()
return body(vars)
}
If you cannot add overloads for some reason, you can pass an "immediately invoked" closure instead. Because of @autoclosure
, this closure isn't actually immediately invoked.
myEnvironment({
let x = 1
let y = 2
let z = 3
return [x, y, z]
}()) { x in
vars[0] + vars[1] + vars[2]
}