[swift-evolution] [Pre-Proposal-Discussion] Union Type - Swift 4

Maximilian Hünenberger m.huenenberger at me.com
Mon Aug 15 09:29:40 CDT 2016


I considered the enum approach but it is very tedious to use "space.add(.point(point))" which also doesn't add any clarity.
The other approach where we add the properties of a Point as associated values also has a major drawback:

// you cannot create a point without "erasing" it's type
let point = GeometryValue.point(x: 4, y: 5)

// if you already have a point instance
"space.add(.point(x: point.x, y: point.y))"

If the union type feature is implemented the intersection of a Point and a Line returns (Point | Line) which is a subtype of a general GeometryValue eg. (Point | Line | Plane) and additionally cannot be checked for a Plane since it doesn't make sense.

The problem with a protocol is that there are only a few methods in common and again in a method like intersect there is no exhaustiveness check in switches.

Best regards
Maximilian

> Am 12.08.2016 um 17:16 schrieb Sean Heber <sean at fifthace.com>:
> 
> As an aside, you could use an enum instead of a protocol to avoid the problem of not having exhaustive switches:
> 
> enum GeometryValue {
>  case point(Point)
>  case line(Line)
> }
> 
> And perhaps (depending on circumstances) you might not even need a Point and Line struct, so you could just put those values inside the enum:
> 
> enum GeometryValue {
>  case point(x: Float, y: Float)
>  case line(x: Float, y: Float, angle: Float)
> }
> 
> However personally, I think using a protocol is the more Swifty approach to this problem. If I end up not having any common properties or functions that apply to that one umbrella protocol, then I consider that a signal that I’m modeling my solution incorrectly.
> 
> l8r
> Sean
> 
> 
>> On Aug 12, 2016, at 6:24 AM, Maximilian Hünenberger via swift-evolution <swift-evolution at swift.org> wrote:
>> 
>> Hi Cao,
>> 
>> I would be in favor until I find another approach to this problem:
>> 
>> Consider you have a geometry framework and two types: Point and Line
>> 
>> An intersection between two lines can be either none, a point or a line (if both are identical).
>> 
>> The return type would probably be (Point | Line)?
>> 
>> I've modeled it with an empty protocol "GeometryType". However this has a major disadvantage:
>> If you have a general "GeometryType?" you have to cast it in a switch to the specific type.
>> In case of (Point| Line)? the switch statement can be checked for exhaustiveness.
>> 
>> For future directions:
>> 
>> There should also be a subtype relationship:
>> 
>> let tu: (T | U) = T()
>> let tuv: (T | U | V) = tu // works
>> 
>> 
>> Overloaded functions/operators could also take Union types based on their overloads:
>> 
>> func take(_ i: Int) -> String { ... }
>> 
>> func take(_ s: String) -> Int? { ... }
>> 
>> let value: (Int | String) = "1234"
>> let value2 = take(value) // returns (String | Int?)
>> 
>> Best regards
>> Maximilian
>> 
>>> Am 11.08.2016 um 03:28 schrieb Cao Jiannan via swift-evolution <swift-evolution at swift.org>:
>>> 
>>> Hi all,
>>> 
>>> I want to make a discussion about union type for swift 4.
>>> See https://github.com/frogcjn/swift-evolution/blob/master/proposals/xxxx-union-type.md
>>> 
>>> Add union type grammar, represents the type which is one of other types.
>>> 
>>> var stringOrURL: String | URL = "https://www.apple.com"
>>> Now, if we using the new union type feature, we can declare type conveniently, No other type declaration, and compiler will automatically calculate the common interface.
>>> 
>>> func input(value: A | B |
>>> C) {
>>> 
>>> print(value.commonProperty) // type checker will calculate the common interface, developer just use it out of box
>>> 
>>> 
>>> switch
>>> value {
>>> 
>>> case let value as
>>> A:
>>> 
>>> // value is type A
>>> 
>>> 
>>> print(value.
>>> propertyInA)
>>> 
>>> case let value as
>>> B:
>>> 
>>> // value is type B
>>> 
>>> 
>>> print(value.
>>> propertyInB)
>>> 
>>> case let value as
>>> C:
>>> 
>>> // value is type C
>>> 
>>> 
>>> print(value.
>>> propertyInC)
>>>    }
>>> 
>>> // there is no default case other than A, B or C. we already declared that.
>>> 
>>> }
>>> 
>>> Note: A, B, C can be either class or protocol, or any other types. This leaves developer more freedom.
>>> 
>>> 
>>> Impact on existing code
>>> 
>>>    • This is a new feature, developer who need declare common type will alter to this new grammar.
>>>    • Enum based version optional or IUO will be replaced by Union-based ones. Any optional type will automatically replaced by union type
>>> 
>>> 
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 


More information about the swift-evolution mailing list