2015-10-17 3 views
6

Это компилирует:Неоднозначность ссылки на член 'печати' - (? Объем внутри Swift закрытия)

let s = SignalsService() 
s.addListener("key", callback: { a, b in print("success") }) 

Это не:

let s = SignalsService() 
let cb = { a, b in print("success") } 
s.addListener("key", callback: cb) 

Метательного ошибку Ambiguous reference to member 'print' на let cb = ... линии.

Почему это так?

ответ

7

В

s.addListener("key", callback: { a, b in print("success") }) 

компилятор может определить тип закрытия из контекста, то есть от типа метода addListener(). Если этот метод , например, объявлен как

func addListener(key : String, callback: (Int, Int) -> Void) 

то компилятор может сделать вывод, что аргумент

{ a, b in print("success") 

является замыкание принимает два Int параметров и возвращение Void.

В

let cb = { a, b in print("success") } 

там нет такого контекста, поэтому компилятор не может знать тип закрытия. Тип возврата можно определить как Void, поскольку замыкание состоит из одного выражения, , но вы должны указать типы параметров, например.

let cb = { (a : Int, b : Int) in print("success") } 
+0

Большое объяснение спасибо. :) –

+0

Спасибо Мартину. JBM –

+0

Также вы получаете эту ошибку, когда функция обратного вызова должна возвращать значение, но вы еще не набрали «возвращаемое значение» в закрытие ... –

2

Расширение на превосходном ответе @ MartinR.

Swift должен быть в состоянии сделать вывод, что cb имеет тип (Int, Int)->(), или вы можете явно задать тип:

let cb: (Int, Int)->() = { a, b in print("success") } 

Тогда вы могли бы заметить, что a и b не используются и заменить их _:

let cb: (Int, Int)->() = { _ in print("success") } 

Почему мы можем уйти с помощью одного _, когда функция принимает 2 параметра? В этом случае Swift знает, что есть 2 параметра, поэтому _ заменяет кортеж, содержащий все параметры. Он заменяет (_, _).


Вы можете использовать _ с @ MartinR отвечают:

let cb = { (_:Int, _:Int) in print("success") } 

или вы можете написать это нравится:

let cb = { (_:(Int, Int)) in print("success") } 

, который может быть прочитан как:

cb принимает два параметра типа Int, который он игнорирует и печатает «успех»