Welp, I got something working, but it's a little bit hacky. Would love to know if there's a more elegant way to do this currently, or if it's a limitation of what we've got so far. (It seems like there may not be a way to iterate over elements of the pack and "short-circuit" partway through, except for throwing an error?)

struct _UnwrapError: Error {}

func zip<each T>(_ pack: repeat (each T)?) -> (repeat each T)? {
  do {
    return (repeat try (each pack).orThrow())
  } catch {
    return nil
  }
}

extension Optional {
  func orThrow() throws -> Wrapped {
    guard let value = self else { throw _UnwrapError() }
    return value
  }
}
3 Likes