[swift-evolution] Union instead of Optional

Austin Zheng austinzheng at gmail.com
Mon May 16 05:37:19 CDT 2016


I'm sorry, but I don't understand the point you are trying to make.

If you pass in a value of type (A | B | C) to a function, what might you want to do with that value?

If you want to do one thing if the value is type A, something else if the value is type B, and something else if the value is type C, then you need to switch or otherwise type check the value at runtime. You can't get around this, no matter whether you use enums, protocols, generics, or union type.

If you want it to do something that A, B, and C all support, use a generic and/or a protocol. In this case limiting the inputs to only those three types is probably a design smell. The whole point of a shared interface is that it only matters that the interface is properly implemented by a type, not what that type is.

If you don't care about doing anything with the value, just make your function generic: func<T>(input: T).

Austin


> On May 16, 2016, at 3:29 AM, Cao Jiannan <frogcjn at 163.com> wrote:
> 
> 
> 
> Consider this case:
> 
> class A {
>     var someCommonProperty: Int = 0
> }
> class B {
>     var someCommonProperty: Int = 0
> }
> class C {
>     var someCommonProperty: Int = 0
> }
> 
> protocol UnionABC {
>     var someCommonProperty: Int
> }
> 
> extension A: UnionABC {}
> extension B: UnionABC {}
> extension C: UnionABC {}
> 
> 
> ===================== If we using protocol
> 
> 
> func input(value: UnionABC) {
>     print(value.someCommonProperty) // Compiler will know their common properties automatically.
>     if value is A {
>         
>     } else if value is B {
>         
>     } else if value is C {
>         
>     } else {
>         // There are other cases? Compiler doesn't know
>     }
> }
> 
> let a = A()
> input(a)
> 
> ===================== If we using union
> 
> func input(value: (A | B | C)) {
>     print(value.someCommonProperty) // Compiler will know their common properties automatically.
> 
>     if value is A {
>         
>     } else if value is B {
>         
>     } else if value is C {
>         
>     } else {
>         // There no other cases, so the compiler trigger a warning.
>     }
> }
> 
> let a = A()
> input(a)
> 
> 
> =====================
> 
> If using generic enum,
> the compiler doesn’t know the type relation between generic union with original type.
> class A and UnionOf3<A,B,C> are totally two different types, has no relationship.
> But class A and (A | B | C) keeps a relationship.
> 
> If using union, these two cases will be allowed:
> 
> let a = A()
> let union: (A|B|C) = a // Automatically wrap.
> 
> a == union // Can be compared, Yes
> 
> sub-typing: 
> 
> var fn0: A->Void = {print(v0)}
> var fn1: (A|B)->Void = {print(v0)}
> 
> fn0 = fn1 // Original Type and Union Type has a sub-typing relationship, OK
> 
> var fn2: (A|B|C)->Void = {print($0)}
> 
> fn0 = fn2 // OK
> fn1 = fn2 // OK
> 
> 
>> 在 2016年5月16日,18:17,Austin Zheng <austinzheng at gmail.com <mailto:austinzheng at gmail.com>> 写道:
>> 
>> This doesn't explain how I can use 'value' once an A() is passed into the function:
>> 
>> func input(value: (A | B | C)) {
>>     
>> }
>> 
>> If A, B, and C are not related via protocol or class inheritance, then there is almost nothing you can do with value. Otherwise you still need to test against the concrete type using a case statement or a if-else ladder.
>> 
>> The other 'gain' is being able to call 'input(A())', rather than 'input(.caseA(A()))'. I agree that the first form is prettier than the second one. I also think you could make the language pervasively prettier and more expressive by allowing for all sorts of implicit conversions. At some point clarity at the point of use beats conciseness, especially when code within a complex codebase needs to be maintained.
>> 
>> I understand that this is largely a matter of style - different people value different things, and that's wonderful. I welcome a formal proposal submitted to the swift-evolution process, and if one appears I'm happy to consider it in more detail and argue for or against it based on that.
>> 
>> Austin
>> 
>> 
>> 
>> On Sun, May 15, 2016 at 3:34 AM, Cao Jiannan <frogcjn at 163.com <mailto:frogcjn at 163.com>> wrote:
>> for example, there is a method input union of 3 types: A, B, C,
>> 
>> This is the three class.
>> 
>> class A {}
>> 
>> class B {}
>> 
>> class C {}
>> 
>> This is how it implemented under Swift 2:
>> 
>> enum UnionABC {
>>     case classA(A)
>>     case classB(B)
>>     case classC(C)
>> }
>> 
>> func input(value: UnionABC) {
>>     
>> }
>> 
>> let a = A()
>> let b = B()
>> let c = C()
>> input(UnionABC.classA(a))
>> 
>> 
>> It needs announce all the cases and name each cases and cannot use class names as their case names.
>> 
>> what about using union? It is more easy and rational.
>> 
>> 
>> func input(value: (A | B | C)) {
>>     
>> }
>> 
>> let a= A()
>> input(a)
>> 
>> Or you can implement it with protocol and extension, but compiler will not know how many cases it should have.
>> 
>> 
>> protocol UnionABC {
>>     
>> }
>> 
>> extension A: UnionABC {}
>> extension B: UnionABC {}
>> extension C: UnionABC {}
>> 
>> 
>> func input(value: UnionABC) {
>>     if value is A {
>>         
>>     } else if value is B {
>>         
>>     } else if value is C {
>>         
>>     } else {
>>         // There are other cases? Compiler doesn't know
>>     }
>> }
>> 
>> let a = A()
>> input(a)
>> 
>> 
>> 
>>> 下面是被转发的邮件:
>>> 
>>> 发件人: frogcjn at 163.com <mailto:frogcjn at 163.com>
>>> 主题: 回复: [swift-evolution] Union instead of Optional
>>> 日期: 2016年5月15日 GMT+8 18:00:55
>>> 收件人: Austin Zheng <austinzheng at gmail.com <mailto:austinzheng at gmail.com>>
>>> 
>>> 
>>> Enum and Union are two things.
>>> 
>>> If you use Enum to implement Union, you should announce it with case name.
>>> 
>>> Another issue using enum instead of union is that,  union can combine types as many as possible, you just write ( A | B | C ... | Z), but for enum, you should carefully announce it for each case. 
>>> 
>>> 在 2016年5月15日,15:22,Austin Zheng <austinzheng at gmail.com <mailto:austinzheng at gmail.com>> 写道:
>>> 
>>>> In addition, not everything in Swift can be modeled in terms of inheritance relationships.
>>>> 
>>>> I'm a little curious as to why union types keep on coming up, when enums can do everything they can and much more (methods, constraints on generic types, conformance to protocols).
>>>> 
>>>> Austin
>>>>>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>> 
>>>>> _______________________________________________
>>>>> swift-evolution mailing list
>>>>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> 
>> 
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160516/34993ce4/attachment.html>


More information about the swift-evolution mailing list