Enum literals, good? bad? what do you think?

Steven Schveighoffer schveiguy at gmail.com
Thu Jul 22 18:16:13 UTC 2021


On 7/22/21 1:19 PM, Walter Bright wrote:
> On 7/22/2021 9:16 AM, Steven Schveighoffer wrote:
>> ```d
>> enum A
>> {
>>     one,
>>     two,
>>     three
>> }
>>
>> enum B
>> {
>>     one,
>>     two,
>>     three
>> }
>>
>> void foo(A a, B b) {... }
>>
>> // how to call foo without having to specify `A.one` or `B.one`?
>> ```
>>
>> In Swift, `.symbol` is specifically for type properties, and fit 
>> perfectly for enums (and other things, see 
>> [here](https://www.swiftbysundell.com/tips/using-dot-syntax-for-static-properties-and-initializers/)). 
> 
> 
> 
> How does that interact with function overloading?

Swift is known for "giving up" on expression inference, so possibly it 
could lead there.

But note that Swift (and objective C) have significant parameter names, 
which means in many cases you *must* name the parameters when calling. 
This helps with overloading quite a bit (in fact, in Objective C there 
was no overloading, as the parameter names were part of the function name).

Which is to say, the situation in Swift is definitely different than the 
situation in D. Overloads are handled differently, and expectations are 
significantly different.

I tried out some stuff:

```swift
import Foundation

enum Foo {
     case a
     case b
     case c
}

enum Bar {
     case a
     case b
}

func test(_ : Foo) { print("test a"); }
func test(_ : Bar) { print("test b"); }

test(.a) // error, ambiguous
test(Foo.a) // test a
test(Bar.a) // test b
test(.c) // test a
```

So it seems to work as one might expect. Since `.c` can only match the 
first, it's used.

> 
> I looked at the Swift reference manual 
> https://docs.swift.org/swift-book/ReferenceManual/Expressions.html and 
> couldn't find answers there.
> 
> Seems to me there'd be a combinatorial explosion as the resolver will 
> have to re-run the match for all different resolutions for 
> `.identifier`.

But what is "all" resolutions? A combinatorial explosion of 1 or 2 
possibilities isn't bad. Remember, the symbol lookup *requires* a 
contextual type. For example:

```swift
var x = .identifier // Compiler error, no type, even if only one type in 
scope has a member `identifier`
var y : SomeEnum = .identifier  // OK
var z : SomeEnum
z = .identifer // OK, we infer the meaning from the type of z
```

I know D doesn't do this. But it's also not the same as what you are saying.

> Even if the compiler does try them all and find a best 
> match, for the user reading the code I doubt it would be straightforward 
> to figure out manually which is the right match. It's already hard enough.

The identifier comes from the expression target's inferred type. There 
are still ambiguous cases, where the compiler is going to give up. But 
the lookup doesn't involve the whole world either.

Before you go on arguing that D doesn't do this, and shouldn't, I know. 
It's not that I'm trying to convince you that it should, I'm just 
showing what has been requested and how it differs from the "mixin 
solution".

> 
> With the alias mixin proposed, the answer is simple. Two different enums 
> in the same scope with the same member names will cause a compile time 
> error.

The answer is, there is no shortcut, just type out the full enum names. 
With Swift you do not need to.

-Steve


More information about the Digitalmars-d mailing list