bjhomer
(BJ Homer)
1
Is it possible to call a function with a parameter pack? Here's what I'm trying to do:
func magic<each T, U>(_ inputs: repeat each T, transform: (repeat each T)->U) -> U {
// error: Cannot pass value pack expansion to non-pack parameter of type 'repeat each T'
return transform(inputs)
}
let x = magic(1) { $0 * 2 }
let y = magic(1, 2, 3) { $0 * $1 + $2 }
func middleValue(a: Int, b: Int, c: Int) -> Int {
return [a, b, c].sorted()[1]
}
let z = magic(14, 12, 5, transform: middleValue)
I want to take the pack of inputs and pass them as the various arguments of transform. Is there a way to do this?
2 Likes
Nobody1707
(Nobody1707)
2
Yes, it's quite easy actually. You just have to expand the parameter pack.
func magic<each T, U>(_ input: repeat each T, transform: (repeat each T)->U) -> U {
return transform(repeat each input)
}
let x = magic(1) { $0 * 2 }
let y = magic(1, 2, 3) { $0 * $1 + $2 }
func middleValue(a: Int, b: Int, c: Int) -> Int {
return [a, b, c].sorted()[1]
}
let z = magic(14, 12, 5, transform: middleValue)
1 Like
In fairness to @bjhomer, variadic generics are a bit unintuitive. I too looked at his example and couldn't immediately see why it didn't work, given it's obviously well-formed.
It's ironic that the compiler error message includes the magic string required to make this work - neatly quoted and everything! - yet is still inscrutable.
Nobody1707
(Nobody1707)
4
Yeah, I only got it right away because i'm used to C++ parameter packs. Where you have to return transform(std::forward<Input>(input)...); which is even less scrutible.
Edit: Yeah, you'd think that error message would include the fixit.
bjhomer
(BJ Homer)
5
Ah, that makes sense. Thank you!