Amzd
(Casper Zandbergen)
1
Is shorthand the preferred way to write ifelse statements in Swift when working with generics?
protocol SomeExample {
var id: String { get }
init(id: String)
}
struct Object: SomeExample {
var id: String
}
class Source {
func get<T: SomeExample>(completion: ([T]) -> Void) {
completion([T(id: "")])
}
}
var outside: Object?
let source = Source()
// Error: Generic parameter 'T' could not be inferred
source.get(completion: {
if let first: Object = $0.first {
outside = first
} else {
fatalError()
}
})
// I understand this is easier to infer
source.get(completion: {
outside = $0.first
})
// But this should definitely be harder than the if
// statement that literally states the type but it
// runs fine
source.get(completion: { objects in
objects.first != nil ? {
outside = objects.first
}() : {
fatalError()
}()
})
jrose
(Jordan Rose)
2
Swift's rule for type inference in closures is that if the closure contains multiple statements, the body is not used to determine its type. This matches the behavior outside of a closure, where later statements in a function do not affect the types of earlier statements in the function, but it does produce a discontinuity when you go from one statement to two.
anandabits
(Matthew Johnson)
3
This is a good motivation for expanding what can be done with expressions.
jrose
(Jordan Rose)
4
It's a motivation. I'm not sure it's a good one because (as frequently complained) massive expressions result in worse type-checker performance (something that may be possible to improve) and more opaque diagnostics (something that's probably inherent, at least to some degree).
anandabits
(Matthew Johnson)
5
Yes, it would require judicious use for sure. But I run across code regularly that would be improved by it. Simple closures with verbose return types that could be inferred are a relatively common example. I could be wrong, but I don’t think the cases I have in mind would run into significant type checker performance issues.