I strongly disagree with using some
for generics. some
in argument position and generics are dissimilar, but the syntax change will make them similar.
As discussed in the Structural opaque result types thread, (some P) -> (some P)
would have following behavior.
// take opaque Numeric value and return opaque Numeric value.
let foo: (some Numeric) -> some Numeric = { (value: Double) in value * 2 }
let doubleValue = 4.2
foo(doubleValue) // error (since some Numeric is opaque)
foo(4) // OK (due to ExpressibleByIntegerLiteral conformance)
foo(.zero) // OK (due to static member requirement)
However, if we adopt some
for generics, the behaviors of closure and function get torn.
func foo(value: some Numeric) -> some Numeric { return value * 2 }
let doubleValue = 4.2
foo(doubleValue) // OK (since value is generic)
foo(4) // OK (since value is considered as Int)
foo(.zero) // error (since there is no way to infer generic type parameter)
It would be really confusing for many developers. What is wrong here is using some
for generics. some
in the argument position should be also opaque in function.
If we want to add sugar, then we should use any
for generics.
// two functions behave the same
func foo(value: any Numeric) -> some Numeric { return value * 2 }
func foo<T: Numeric>(value: T) -> some Numeric { return value * 2 }
Actually, Rust explained its impl
as hybrid of generic any
and reverse generic some
in RFC 1951. I think this is logical direction.
As of existential types, we should search some other prefix like exist
.