> Am 16.05.2016 um 12:07 schrieb Austin Zheng via swift-evolution 
> <[email protected]>:
> 
> Precisely. To me unions are to enums with associated type the same way tuples 
> are to structs. One is named, has well-defined semantics, can conform to 
> protocols, can have complex internal structure, can have methods, etc. The 
> other is ad-hoc and lightweight, easy to define at the site of use, best 
> suited for simple purposes, has special syntax to support it. 
> 
> Even if we can extend tuples in the future, though, I wouldn't want structs 
> to go away. When exceeding some level of complexity structs are just more 
> explicit than tuples, and therefore easier to understand.
> 
> Finally, please note that Ceylon is a pervasively object-oriented language 
> with a single root superclass. Neither of those is true for Swift, which 
> chooses to solve a lot of problems in a different (and I would argue, 
> superior) way. So solutions that might work well in Ceylon might not be 
> suited for Swift, at least not without modification, and vice versa. The core 
> team could certainly have chosen to model Swift's type system after that of 
> e.g. Scala, but they chose not to, and I think they did so for good reason.

Swift has a root class, it is called SwiftObject and it's visible from 
Objective-C ;) Just thinking about it.. it makes sense: the whole 
reference-counting-stuff has to live somewhere in the object, and there has to 
be some kind of isa-pointer to allow for subclassing (and Objective-C 
interoperability). So there is some common behavior regarding all classes 
defined from Swift (they all implement retain, release, autorelease, isEqual:, 
class, respondsToSelector:, the whole NSObject-protocol...) => what I want to 
express: Java has a root-class, C++ has no root class - that's uncontested; but 
Swift is somewhere in-between IMHO.

And for enums and unions.. I think they are different. enums are "sum-types" 
and unions are... well... "union-types", when you think of data types as sets. 
E.g. if A, B are data types (sets), then an enum that can be either anA(A) or 
aB(B) can be thought of as the set A+B (and if A \intersect B \not\eq 
\emptyset, you can think of this as (0,A)\union (1,B) ). A union B is not the 
same. In C, the unions are not even safe, because they are not discriminated in 
any way. In Swift they make an isomorphic set if A and B are disjoint. If 
A=String and B=Int, A `enum` B is isomorphic to A `union` B (sorry for abusing 
Haskell syntax :-/ ). But if A=Iterable<String> and B=Array<String>, they are 
not the same, because now A is a superset of B. So A `enum` B is a strict 
superset of A `union` B (== A). I can already imagine weird bugs coming to the 
surface from this distinction, all of which can be solved by disallowing union 
types altogether.

Therefore I think that unions are not worth the trouble at all. And they are 
even possible right now: Instead of writing

    union MyUnion { Int, String }
    // or typealias MyUnion = (Int | String) // ?

you'd have to write

    protocol MyUnion {}
    extension Int: MyUnion {}
    extension String: MyUnion {}

The two definitions are basically equivalent, and the second is already valid 
Swift.

I have used unions a few times in C though, e.g. for converting from void* to 
int or stuff like that, at a time when I didn't know about reinterpret_cast 
(Swift: unsafeBitcast) yet. The few occasions where they are use in the C 
standard library, they are always discriminated, like a union between a 
struct(int type, float foo, ...) and another struct(int type, char bar[20], 
...) where the type parameter is in both values and can be used to distinguish 
them. In Swift they are always distinguishable because of runtime type 
information (except for the case described above), so you can as well just use 
an enum and make that information obvious. To unpack the information you can 
use `if let` when dealing with a union, and you can use `if case` or `switch` 
when dealing with an enum. I don't see how unions would be more convenient to 
be worth the trouble. Swift unions would be like (C unions + RTTI (runtime type 
information)), with RTTI replacing the discriminator element of enums, except 
when the types overlap. So I doubt that anyone will find a decent (realistic!) 
use-case that is not just as easily (and conveniently) implemented using enums. 
I think I just proved that there is no such use case ;) The best way to 
convince me otherwise would be to provide a realistic piece of example code.

Regards,
Michael

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to