How to reference a generic function when a concrete version also exists?


#1

If I write a generic function like this:

func f<T>(_ x: T) { print("Generic: \(x)") }

I can pass it to another function like this:

func g(_ fn: (Int) -> Void) { fn(0) }
g(f) // Prints “Generic: 0”

However if I *also* write a non-generic function like this:

func f(_ x: Int) { print("Int: \(x)") }

Then when I make the same call as before:

g(f) // Prints “Int: 0”

It passes in the new, non-generic version.

Is there something I can do, with both versions of f defined, to pass the
generic f into g?

Nevin


(David Sweeris) #2

Not that I know of. Once the code path gets to g(), the compiler knows that the function is specifically an (Int)->Void, as opposed to the generic (T)->Void, and it’ll always go for the most specific overload. AFAIK, anyway.

- Dave Sweeris

···

On May 2, 2017, at 4:39 PM, Nevin Brackett-Rozinsky via swift-users <swift-users@swift.org> wrote:

If I write a generic function like this:

func f<T>(_ x: T) { print("Generic: \(x)") }

I can pass it to another function like this:

func g(_ fn: (Int) -> Void) { fn(0) }
g(f) // Prints “Generic: 0”

However if I *also* write a non-generic function like this:

func f(_ x: Int) { print("Int: \(x)") }

Then when I make the same call as before:

g(f) // Prints “Int: 0”

It passes in the new, non-generic version.

Is there something I can do, with both versions of f defined, to pass the generic f into g?


(Jordan Rose) #3

You can always throw away infromation by making a new generic context:

func callF<T>(_ x: T) -> Void {
  f(x)
}
g(callF)

Jordan

···

On May 2, 2017, at 16:53, David Sweeris via swift-users <swift-users@swift.org> wrote:

On May 2, 2017, at 4:39 PM, Nevin Brackett-Rozinsky via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

If I write a generic function like this:

func f<T>(_ x: T) { print("Generic: \(x)") }

I can pass it to another function like this:

func g(_ fn: (Int) -> Void) { fn(0) }
g(f) // Prints “Generic: 0”

However if I *also* write a non-generic function like this:

func f(_ x: Int) { print("Int: \(x)") }

Then when I make the same call as before:

g(f) // Prints “Int: 0”

It passes in the new, non-generic version.

Is there something I can do, with both versions of f defined, to pass the generic f into g?

Not that I know of. Once the code path gets to g(), the compiler knows that the function is specifically an (Int)->Void, as opposed to the generic (T)->Void, and it’ll always go for the most specific overload. AFAIK, anyway.