For example:
func f(x: Int) -> Int { return x } func h(f: @escaping (Int) -> Any) { if (f is (Int) -> Int) { print(f(1)) } else { print("invalid") } } h(f: f)
I expect it to print out 1
but it actually prints out invalid
.
There's a workaround using generics:
func intF(x: Int) -> Int {
return x
}
func stringF(x: Int) -> String {
return "\(x)"
}
func h<T>(f: (Int) -> T) {
if (T.self == Int.self) {
print(f(1))
} else {
print("invalid")
}
}
h(f: intF) // prints: 1
h(f: stringF) // prints: invalid
Using Any
is almost always a sign of code smell, you should try to rely as much as possible of the type safety that Swift provides. You can achieve this by making h
generic, thus verifiable at compile time.
// 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, you could even give up the generic overload, thus you'll have for free compile checks instead of runtime failures (much, much reliable and predictive)
You can rewrite h
into a generic function:
func h<T>(f: @escaping (Int) -> T) {
if T.self == Int.self {
print(f(1))
} else {
print("invalid")
}
}
But the better way to to write type-specific overloads for h
and a generic catch-all for the rest (if you need it at all).
来源:https://stackoverflow.com/questions/41409543/how-to-check-predicate-function-type-in-swift