Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to disambiguate functions with differences only in parameter names in Swift

Tags:

swift

I have the following functions:

func moveThing(thing: AnyObject, toLeft length: Int) {}
func moveThing(thing: AnyObject, toRight length: Int) {}

However, when I pass one of the functions as a parameter, compiler complains about "Ambiguous use of 'moveThing'"

func exec(function: (AnyObject, Int) -> ()) {}
exec(moveThing) // Apparently ambiguous
exec(moveThing as (AnyObject, toLeft: Int) -> ()) // Still ambiguous

How can I solve the ambiguity?

like image 924
Guoye Zhang Avatar asked Feb 27 '15 16:02

Guoye Zhang


2 Answers

Swift Evolution proposal SE-0021 addressed this by allowing moveThing(_:toLeft:) to disambiguate these functions, and it is implemented in Swift 2.2.

like image 118
Guoye Zhang Avatar answered Dec 01 '22 13:12

Guoye Zhang


I know this is an old thread, but I ran into this related situation recently. Might help somebody.


TLDR

Ultimately I solved the problem by just wrapping the method call in a closure like this:

let cancel: (Text) -> Alert.Button = { .cancel($0) }



Long Winded Explanation

When I type Alert.Button.cancel (from the SwiftUI framework), auto-complete shows me these options:

cancel(action: (() -> Void)?) // 1
cancel(label: Text) // 2
cancel() // 3
cancel(label: Text, action: (() -> Void)?) // 4

Naturally I thought this bit of code should work:

let cancel: (Text) -> Alert.Button = Alert.Button.cancel(_:)

However, the compiler says Cannot convert value of type '((() -> Void)?) -> Alert.Button' to specified type '(Text) -> Alert.Button'. Apparently it translates that signature to mean method 1 instead of method 2.

As it turns out, method 2 does not actually exist. Looking at the actual declarations in Alert.swift we find:

public static func cancel(_ label: Text, action: (() -> Void)? = {}) -> Alert.Button
public static func cancel(_ action: (() -> Void)? = {}) -> Alert.Button

So, cancel(label:) is rendered by auto-complete from cancel(_:action:) because the parameter action has a default value.

Conclusion: I made the mistake of assuming auto-complete was showing me individual method declarations. If the compiler tells you a method signature doesn't match what you expect, check the method declaration.

like image 27
Scott Levie Avatar answered Dec 01 '22 12:12

Scott Levie