[swift-evolution] [Pitch] Small bit of sugar for enum case with Void associated value

Xiaodi Wu xiaodi.wu at gmail.com
Tue Jul 25 16:20:41 CDT 2017


Yes, I discussed this some time back. It breaks some things with overloads,
if I recall, but off the top of my head not recalling what.

At some point, I also suggested regarding any case without associated
values as equivalent to a case with an associated value of type Void. This
was never adopted. There _is_ an underlying issue with that idea, as the
property “foo” is not the same as the method “foo(_: Void)”, and it is even
permitted to have both of these on the same type. The purpose of the most
recent Swift proposal on enum cases was to align the syntax with functions
as closely as possible; if overloading the base name of a case (as proposed
back then to favorable reviews) is ever allowed, then the same will
naturally be possible with enums (that is, a case named “foo” and another
named “foo(_: Void)” in the same type).

In the case of concrete enums, a case with associated value of type Void
can be given a default value once they are supported (already approved);
the trouble here is that in the generic case presented here the same is not
possible. It is unclear to me whether this special rule would see broad
use, as it appears to come into play *only* for a generic enum. Moreover,
in the one scenario I can think of, it reads cryptically: “let foo =
Optional.some” would then be allowed (while “let bar = Optional.none” still
would not). The upside is that it avoids having to write four or six
letters (“Optional.some(Void())” is never necessary, as it’s also just
“Optional.some(Void)”, and that reads acceptably in my view).
On Tue, Jul 25, 2017 at 15:26 David Sweeris via swift-evolution <
swift-evolution at swift.org> wrote:

>
> On Jul 25, 2017, at 12:38, Robert Bennett via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> Currently if you have the following enum:
>
> enum E<T> {
> case c(T)
> }
>
> then if T is Void, you have to write one of the following:
>
> let x: E<Void> = .c(Void())
> let y: E<Void> = .c(())
>
> Looks awkward, no? In this case you can omit `<Void>` after `E` because it
> can be inferred, but if writing a (non-generic) function taking an argument
> of type `E<Void>`, then the `<Void>` cannot be omitted, and you still have
> to write `.c(())` for the case name.
>
> I’m proposing that for enum cases with a single associated value of Void
> type, or of a generic type that is equal to Void in some instance, you may
> omit the parentheses altogether and merely write
>
> let x: E<Void> = .c
>
> The rationale is twofold: first, double parentheses just looks bad;
> second, there is only a single value of type Void, which means the
> associated value of `.c` is trivially inferable, and hence should be
> omissible.
>
> I am not proposing that a bare `E.c` imply a type of `E<Void>` — `E.c`
> should still be illegal in the absence of specification of the generic type
> — only that when the type is known to be `E<Void>`, `.c` can replace
> `.c(())`.
>
> Thoughts?
>
>
> My first response is +1
>
> My second response is to ask just how much would it break things to expand
> this and allow omitting the argument anywhere its type is known to be Void?
> Maybe by implicitly providing a default value of `()` wherever there's a
> `Void` argument? Like make `func foo(x: Void) {...}` implicitly become `func
> foo(x: Void = ()) {...}`? I have a sneaking suspicion that this
> question's already been asked, but I'm not sure.
>
> - Dave Sweeris
> _______________________________________________
> 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/20170725/7cb71fe2/attachment.html>


More information about the swift-evolution mailing list