> On Aug 18, 2017, at 8:13 PM, Jonathan Hull <jh...@gbis.com> wrote: > > It is different though. > > Sure, with a little bit of sugar, it can be used to make something that looks > a bit like union types, but it should avoid the complexity in the type > checker which caused that to be on the rejected list. In this case 'Int | > String' is just sugar for '.int(Int) | .string(String)’, which creates an > anonymous enum similar to the actual enum shown below. > > Without the sugar, it really just is a quick way to build enums. Without the > sugar, it can be used to make something that looks a bit like union types as > well, but you just have to type .int(Int) | .string(String). I can do that > with enums right now though: > > enum myType { > case int(Int) > case string(String) > } > > This is just a shorthand way of quickly doing the above without giving it a > name.
I see your point, but I think this is still very solidly in a space that we've expressed interest in not pursuing, especially with the long chain of "wouldn't it be great" additions you're suggesting. John. > > > > >> On Aug 18, 2017, at 11:35 AM, John McCall <rjmcc...@apple.com> wrote: >> >>> On Aug 18, 2017, at 6:36 AM, Jonathan Hull via swift-evolution >>> <swift-evolution@swift.org> wrote: >>> The typed throws discussion brought me back to an old thought. >>> >>> I would really like to see a new structural type, similar to tuples, which >>> act as an anonymous enum. These would actually be a distinct type from >>> enums (not sure what to call them), in the same way that structs and tuples >>> are different. They would have a very similar syntax to enums though, so >>> they would be easy to learn. >> >> This is the commonly-rejected "Disjunctions in type constraints" feature. >> >> John. >> >>> >>> There would be two major difference from enums: >>> >>> 1) Because they are structural, they can’t have associated functions or >>> extensions >>> >>> 2) They can concatenate with one another freely >>> >>> For example: >>> >>> func foo( speed: .slow | .med | .fast ){ >>> bar(speed: speed) >>> } >>> >>> func bar(speed: .slow | .med | .fast | .ludicrous) { >>> //but we couldn't call foo here because it doesn’t take >>> .ludicrous >>> } >>> >>> Each case is it’s own mini-type in a way. One ‘.slow’ is equivalent to any >>> ‘.slow’ (even one from a regular enum). Essentially, it is a loosely bound >>> group of cases, and type checking just means seeing if the list/value being >>> passed is a subset of the list of possible cases. >>> >>> I’d also like to see sugar for quick conversion from normal Swift enums: >>> >>> enum Speed { >>> case slow >>> case med >>> case fast >>> } >>> >>> func foo(speed: Speed | .ludicrous) { >>> //we can’t call any functions/extensions of Speed, just like we >>> can’t call a func from int on (Int, Int) >>> } >>> >>> In the above case, Speed gets converted via sugar to “.speed(Speed)” and >>> then gets concatenated with .ludicrous. Ideally, it would have the added >>> ability to truly convert to ".slow | .med | .fast | .ludicrous” when passed >>> to something that doesn’t know about Speed: >>> >>> func foo(speed: Speed | .ludicrous) { >>> switch speed { >>> case .speed(let s): //Do something with the Speed value >>> case .ludicrous: //Do something ludicrous >>> } >>> bar(speed: speed) //This can convert to pass by unwrapping >>> Speed to a bag of cases >>> } >>> >>> func bar(speed: .slow | .med | .fast | .ludicrous) { >>> switch speed { >>> case .slow: // >>> case .med: // >>> case .fast: // >>> case .ludicrous: // >>> } >>> //We can’t reference Speed above because we just passed a bag >>> of potential cases >>> } >>> >>> >>> The end result here is that in addition to building one-off enums quickly, >>> it lets us concatenate and extend enums for use in a limited scope. I >>> don’t know about you, but I run into the situation of “I want exactly this >>> enum, but with one extra case” all the time. >>> >>> I don’t know if we want typed throws, but this type of quick concatability >>> would be very useful for adding/merging potential errors. With the same >>> sugar used on Speed above, it would also allow something similar to Union >>> types, but without the most of the implementation headache that would >>> cause. You can take in multiple types, and you get back something you can >>> switch on to recover the type which was passed: >>> >>> func myFakeUnion(_ intOrStr: Int | String){ >>> switch intOrStr { >>> case .int(let i): //Do something with int >>> case .string(let s): //Do something with string >>> } >>> } >>> >>> myFakeUnion(12) //Sugar! >>> myFakeUnion(.string(“Hey”)) //This works too >>> >>> >>> Finally, I would love to see the switch equivalent of ‘a ? b : c’ in Swift. >>> I am not sure what the best syntax would be, but it would essentially work >>> a bit like like a dictionary: >>> >>> let mph = speed ? [.slow:10, .med:35, .fast:75] >>> >>> >>> Thanks, >>> Jon >>> >>> >>> >>> >>> _______________________________________________ >>> swift-evolution mailing list >>> swift-evolution@swift.org >>> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> > _______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution