Pitching The Start of Variadic Generics

One thing that might be useful as a step towards variadic generics is introducing local generic parameters.

For example, as @xAlien95 pointed out:

func debugPrint<T...>(_ items: T...) 
  where T: CustomDebugStringConvertible
{   
  for (item: T) in items { // <--- Here
    stdout.write(item.debugDescription)
  }
}

The T on the marked line is actually a new, local generic parameter which overrides the name T... in the function declaration. Actually, the T on that line refers to a different type on each iteration of the loop. Using a slightly different syntax, it might look like this:

func debugPrint<T...>(_ items: T...) 
  where T: CustomDebugStringConvertible
{   
  for<ItemType> item in items {
    stdout.write(item.debugDescription)
  }
}

It's a new concept in the language, and is important for variadic generics: each element in the type sequence has a different type, so naturally operations such as iteration or extracting a particular element need to bind new type parameters.

It's also something which would be useful right away - we could use it for unboxing existentials, finally allowing them to be used with generic algorithms. You could imagine something like this syntax being used to unbox an array of heterogeneous collections:

func areEqual(_ leftElements: [Equatable], _ rightElements: [Equatable]) {
  guard leftElements.count == rightElements.count else { 
    return false 
  }
  for<Left, _> (left, _right) in zip(leftElements, rightElements) {
    guard let right = _right as? Left, left == right else {
      return false
    }
  }
  return true
}

areEqual(["string", 42], [true, 99.4]) // false

Which is kind of a silly example, but it demonstrates a level of dynamic typing which we can't even express today. It also shows the overlap the between existentials (and collections of existentials) and variadic generics - they work differently, but ultimately they both deal in abstractions over heterogeneous lists and try to allow lists of types to be used generically.

It would be nice to keep this in mind and design language features which can work for both.

6 Likes