Использование Any
почти всегда признак кода запаха, вы должны попытаться полагаться как можно больше о безопасности типа, что Swift обеспечивает. Вы можете добиться этого, сделав h
общий, таким образом проверяемый во время компиляции.
// the overload that does the actual stuff
func h(f: @escaping (Int) -> Int) {
print(f(1))
}
// this maps to all other types
func h<T>(f: @escaping (Int) -> T) {
print("invalid")
}
h { _ in return "15" } // Invalid
h { 2 * $0 } // 2
Heck, вы можете даже отказаться от родовой перегрузки, таким образом, вы будете иметь для свободных проверок компиляции вместо сбоев во время выполнения (много, много надежных и прогнозирующих)
A kludgey way: 'if f (1) is Int {' – vacawama
Я подозреваю, что тип экземпляра, «завернутый» с помощью 'Any' в поставляемом закрытии' f', не может быть выведен компилятором без фактического вызова 'f '. В глазу компилятора 'f' является замыканием на форме' {arg in;/* ... * /; return someInstanceOfTypeAny} '. Независимо от того, является ли 'someInstanceOfTypeAny' фактически типом' Int' или нет, может быть установлено только путем фактического изучения типа фактического экземпляра _, возвращаемого закрытием 'f'_, например. как предлагает @vacawama. Ниже приведен пример использования шаблона, где 'T' фактически является _concrete type_ (а не оболочкой времени выполнения!) Для каждого вызова' h'. – dfri
@dfri При передаче 'f' в' h' компилятор знает, что тип 'f' is' (Int) -> Int', интересно, почему он не может сузить '(Int) -> Any' до подтипа' (Int) -> Int'? 'f' не является анонимным закрытием без аннотации типа. 'f' хорошо аннотируется. – weakish