How to pass a parameter pack of values to a parameter pack of closures?

Hi! I'm running into a situation with parameter packs where I have some working code… but I am looking for some ways to clean it up (if possible). I am hoping to build this all from production 5.10 Swift.

My situation is I have a parameter pack of some Input types. I then have a parameter pack of closures that produce an Output for every Input. A more advanced use-case might be supporting a unique Output type (another parameter pack). For now I can assume every Input type produces the same Output type.

I am looking for a pattern to "apply" my parameter pack of closures to my parameter pack of inputs. Here are some attempts:

func f1<each Input, Output>(
  input: repeat each Input,
  transform: repeat (each Input) -> Output
) {
  let _ = (repeat each transform(input))
  let _ = (repeat transform(each input))
  let _ = (transform(repeat each input))
}

Those all fail with different errors.

I am unblocked (for now) with this workaround that uses a local helper function:

func f2<each Input, Output>(
  input: repeat each Input,
  transform: repeat (each Input) -> Output
) {
  func _transform<T>(input: T, transform: (T) -> Output) -> Output {
    transform(input)
  }
  let _ = (repeat _transform(input: each input, transform: each transform))
}

This compiles… but I was wondering if there was any way to cut out that extra helper function and perform this work directly.

And then another question I still don't have a great answer for is how might I return that tuple of Output values back?

func f3<each Input, Output>(
  input: repeat each Input,
  transform: repeat (each Input) -> Output
) -> Output {
  func _transform<T>(input: T, transform: (T) -> Output) -> Output {
    transform(input)
  }
  return (repeat _transform(input: each input, transform: each transform))
          `- error: cannot convert return expression of type '(/* shape: each Input */ repeat Output)' to return type 'Output'
}

I've looked through SE-0393 and I'm not sure I see any way to specify that each Input repeat Output type. I am looking for a tuple of Output values that matches the dimension of the Input parameter pack. Is something like that even possible with 5.10? Any more advice about that? Thanks!

You can't directly represent a homogeneous pack.

Either the output needs to be a pack as well…

func map<each Input, each Output>(
  input: repeat each Input,
  transform: repeat (each Input) -> each Output
) -> (repeat each Output) {
  (repeat (each transform)(each input))
}

Or you need this sort of thing.

typealias Unpack<Pack, Value> = Value

func map<each Input, Output>(
  input: repeat each Input,
  transform: repeat @escaping (each Input) -> Output
) -> (repeat Unpack<each Input, Output>) {
  (repeat (each transform)(each input))
}

I don't know if it's possible to avoid that @escaping.

3 Likes

Ahh… I actually think this answers my original question:

func map<each Input, Output>(
  input: repeat each Input,
  transform: repeat (each Input) -> Output
) {
  let _ = (repeat (each transform)(each input))
}

I was looking for the syntax to pass each input to each transform without an extra local helper function. This one compiles with no errors. Thanks!

What are you going to do with it, though? If you can't access the output, it's not "transform"; it's "body".

You can easily iterate over it in Swift 6.0, but you can't stuff the result into a tuple.

1 Like

Ahh… I see. The code compiles but there is nothing I can do with that each Input repeat Output type.