How to write this generic func as a closure: `func isMatch<Element>(_ a: Element, _ b: Element) -> Bool where Element: Equatable { a == b }`

Write this func as closure:

func isMatch<Element>(_ a: Element, _ b: Element) -> Bool where Element: Equatable {
    a == b
}

into something like this:

let isMatch = { (_ a: Element, _ b: Element)  -> Bool in a == b }

How to constraint Element to be Equatable?

So the answer is no-can-do: ios - is it possible to create a generic closure in Swift? - Stack Overflow

But typealiase can have generic.

1 Like

Closures can't have generics, but you can erase the elements to Any and then open them back up to Equatable:

let isEqual: (Any, Any) -> Bool = { lhs, rhs in
  guard
    let lhs = lhs as? any Equatable,
    let rhs = rhs as? any Equatable
  else { return false }
  return open(lhs, rhs)

  func open<T: Equatable>(_ lhs: T, _ rhs: Any) -> Bool {
    lhs == (rhs as? T)
  }
}

isEqual(1, 1)  // true
isEqual("hello", "goodbye")  // false
isEqual(1, "goodbye")  // false

The only thing you lose is the guarantee that both lhs and rhs are the same type, and there are some edge cases around subclasses when opening existentials like this. Oh and I guess there is technically a performance hit, but probably only noticeable if invoked many, many times.

2 Likes

The other (heavyweight) choice is to use a protocol with the generic function as its single requirement, and implement a new local type every time you want a different implementation. Which is possible, but a lot more trouble than a closure, at least today. Maybe a macro?

2 Likes