[swift-evolution] Allowing non-binding pattern matching as a Bool expression?
Kevin Wooten
kdubb at me.com
Thu Dec 10 09:48:11 CST 2015
> On Dec 10, 2015, at 8:42 AM, plx via swift-evolution <swift-evolution at swift.org> wrote:
>
> The motivating/most-common case for me is serialization:
>
> coder.encodeInteger(self.enumerationCase.rawValue, forKey: “case")
> switch self {
> case let .Foo(data): coder.encodeX(data, forKey: “data”)
> case let .Bar(data): coder.encodeY(data, forKey: “data”)
> }
>
Solvable now via…
switch self {
case let .Foo(data):
coder.encodeInteger(…)
coder.encodeX(..)
case let .Bar(data):
coder.encodeInteger(…)
coder.encodeY(…)
}
It’s only missing an integer raw value assigned by the compiler.
> …etc., and the obvious use of the above when decoding (decode the case, switch on it, decode data).
>
> Once you have it it’s occasionally handy in other contexts, but that’s by far the main motivation.
>
>> On Dec 10, 2015, at 9:35 AM, Kevin Wooten <kdubb at me.com <mailto:kdubb at me.com>> wrote:
>>
>> I get the gist of what you are requesting and I can see it might me useful but given that
>>
>> if case .Foo(_) == ex {
>> }
>>
>> Provides comparison, regardless of the # of associated values in .Foo, I’m not sure generating a second enum just to carry a diminished amount of information is worth it.
>>
>>
>>> On Dec 10, 2015, at 8:24 AM, plx via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>>
>>> FWIW, as long as we’re asking for some compiler assistance generating useful enumeration-related boilerplate, I’d like to request that something along these lines be possible in some version of Swift:
>>>
>>> @synthesize_case_enum
>>> enum Example {
>>>
>>> case Foo(X)
>>> case Bar
>>> case Baz(Y)
>>>
>>> }
>>>
>>> …which would then by default expand to something like this:
>>>
>>> enum ExampleCase : Int {
>>>
>>> case Foo
>>> case Bar
>>> case Baz
>>>
>>> }
>>>
>>> extension Example {
>>>
>>> var enumerationCase: ExampleCase {
>>> get {
>>> switch self {
>>> case .Foo(_): return .Foo
>>> case .Bar(_): return .Bar
>>> case .Baz(_): return .Baz
>>> }
>>> }
>>> }
>>>
>>> }
>>>
>>> …in the default case, but with some customization of the synthesized enumeration-case-enum’s details.
>>>
>>> For the remaining proposals:
>>>
>>> - `isX()` is nice (and should always `-> Bool`, IMHO)
>>> - `projectX()` is nice and should:
>>> - *not* be defined for enums w/out associated values
>>> - `-> T?` for enums w/ a single associated value
>>> - -> the full tuple, for enums w/ multiple associated values, e.g.:
>>> - `Foo(A,B)` yields `projectFoo() -> (A,B)?
>>> - `Event(place: Place, time: Time)` -> (place: Place, time: Time)?
>>> - (which is essentially the same as for the single-value case, just making it explicit)
>>>
>>> …which has the benefit of predictability (and if you need more convenience, replace your tuples with actual classes-or-structs).
>>>
>>> Finally, as convenient as the `associatedValue` proposal is down below, it seems better-served by some sort of generalized delegation construct; at a minimum, I don’t think it's that uncommon to have N cases all wrapping the same underlying type, and in such cases working with an `Any?` would feel rather clunky.
>>>
>>>> On Dec 9, 2015, at 3:00 PM, Andrew Bennett via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>>>
>>>> I really like this solution and perhaps you can also go @projectable("empyValue") if the default name is a bad choice. See @obc for similar usage.
>>>>
>>>> On Thursday, 10 December 2015, Alex Lew via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>>> Semantically, I believe enums with more than one associated value are actually just enums with one associated value, of tuple type.
>>>>
>>>> I'm not convinced it would be bad to do magic function generation, but it's worth considering explicit syntax. If we were to use @ compile-time attributes, maybe it could be a word before the case -- like @projectable or @selectable (or some better name)?
>>>>
>>>> enum List<T> {
>>>> @projectable case Empty
>>>> indirect case FirstAndRest(T, List<T>)
>>>> }
>>>>
>>>> generates:
>>>> myList.isEmpty() -> Bool
>>>>
>>>> Another option: some sort of @reflectable attribute on the enum itself.
>>>>
>>>> @reflectable enum Pet {
>>>> case Cat(name: String, color: String)
>>>> case Dog(name: String, breed: String)
>>>> case Bear(name: String, isHibernating: Bool)
>>>> }
>>>>
>>>> And one other option, in a very different direction, that seems weird but maybe has its benefits:
>>>>
>>>> What if we exposed an associatedValue computed property of type Any? (It would be unit type for cases with no associated value.)
>>>>
>>>> You could then do something like this:
>>>>
>>>> enum Contact {
>>>> case Person(String) // name
>>>> case Business(String) // org name
>>>> case FamilyMember(String) // relation name
>>>> case RecentCall(Int) // a contact from caller id, only store the phone number
>>>>
>>>> func name() -> String {
>>>> return associatedValue as? String ?? "Unknown (\(associatedValue as! Int))"
>>>> }
>>>> }
>>>>
>>>> Essentially, it allows you to project out a relatively common associated value (in this case a string) without much boilerplate. It's also just one thing for the compiler to generate, instead of n. Not crazy about any of these... just brainstorming. It may also be that a concise switch-like control flow expression eliminates the need for this.
>>>>
>>>> -Alex
>>>>
>>>> On Wed, Dec 9, 2015 at 11:49 AM, thorsten at portableinnovations.de <javascript:_e(%7B%7D,'cvml','thorsten at portableinnovations.de');> <thorsten at portableinnovations.de <javascript:_e(%7B%7D,'cvml','thorsten at portableinnovations.de');>> wrote:
>>>> I would prefer if no "magic" methods would be generated automatically, but only when marked with @derivestandardmethods (fill in better name here).
>>>>
>>>> As to naming I like the proposal #1 by Alex.
>>>>
>>>> What about enums with more than one associated value?
>>>>
>>>> -Thorsten
>>>>
>>>> Am 09.12.2015 um 07:29 schrieb Alex Lew via swift-evolution < swift-evolution at swift.org <javascript:_e(%7B%7D,'cvml','swift-evolution at swift.org');>>:
>>>>
>>>>> Thanks, Chris, for all the time you're putting into responding to these proposals (and the kindness with which you're responding!). I really like that solution.
>>>>>
>>>>> Brainstorming some names for the auto-generated functions:
>>>>>
>>>>> 1. If a case has no associated values, isX() -> Bool is generated, where X is the case name.
>>>>> If a case has an associated value of type T, asX() -> T? is generated, where X is the case name.
>>>>> This mirrors is/as? operators, which return Bool / Optional respectively.
>>>>> 2. projectX() -> Bool / projectX() -> T?
>>>>> 3. isX() -> Bool / xValue() -> T?
>>>>>
>>>>> Another option (probably the wrong option, but it's worth putting out there) is that instead of returning Bool in the no-associated-value case, we return ()?. This would make me feel better about using the same naming convention (asX(), projectX(), xValue(), etc.) for each case, and would allow for != nil checks on all cases. But it would probably be a little confusing for newcomers to the language.
>>>>>
>>>>> One (potentially misguided) question. I noticed in proposal 0002 (on removing function currying) that there are "plans to move away from the arguments-are-a-single-tuple model" in the near future. Would this also affect associated values of enums? That is, might
>>>>>
>>>>> case Dog(name: String, age: Int, breed: String)
>>>>>
>>>>> one day not have the semantics of a single associated value of type (name: String, age: Int, breed: String)? Or is the de-ML-ification planned only for function arguments?
>>>>>
>>>>> -Alex
>>>>>
>>>>> On Wed, Dec 9, 2015 at 12:45 AM, Chris Lattner <clattner at apple.com <javascript:_e(%7B%7D,'cvml','clattner at apple.com');>> wrote:
>>>>>
>>>>> > On Dec 7, 2015, at 8:05 PM, Alex Lew via swift-evolution <swift-evolution at swift.org <javascript:_e(%7B%7D,'cvml','swift-evolution at swift.org');>> wrote:
>>>>> >
>>>>> > Hi all,
>>>>> >
>>>>> > Curious to hear thoughts on allowing non-binding pattern matches to be used as boolean values outside of an if, guard, for...in, while, switch, etc. Something like:
>>>>> >
>>>>> > enum List<T> {
>>>>> > case Empty
>>>>> > indirect case Link(T, List<T>)
>>>>> >
>>>>> > func isEmpty() -> Bool {
>>>>> > return case .Empty = self
>>>>> > }
>>>>> > }
>>>>>
>>>>> I agree with you that this is a problem that we should solve, but I think it could be solved in a different way. Imagine if:
>>>>>
>>>>> enum Foo {
>>>>> case X(a : Float), Y, Z(a : Int)
>>>>> }
>>>>>
>>>>> automatically synthesized these members (the exact names are just a strawman proposal, not serious :-)
>>>>>
>>>>> extension Foo {
>>>>> func isX() -> Float? {…}
>>>>> func isY() -> Bool {…}
>>>>> func isZ() -> Int? {…}
>>>>> }
>>>>>
>>>>> This would tie into all of the mechanics we have for dealing with optionals, e.g. if/let and ??
>>>>>
>>>>> -Chris
>>>>>
>>>>
>>>>> _______________________________________________
>>>>> swift-evolution mailing list
>>>>> swift-evolution at swift.org <javascript:_e(%7B%7D,'cvml','swift-evolution at swift.org');>
>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>> Untracked with Trackbuster <https://trackbuster.com/?sig>
>>>>
>>>> _______________________________________________
>>>> 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>
>>>
>>>
>>> _______________________________________________
>>> 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>
>>
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151210/2e11949d/attachment.html>
More information about the swift-evolution
mailing list