[swift-evolution] [Idea] Repurpose Void

Dennis Lysenko dennis.s.lysenko at gmail.com
Mon Apr 25 06:12:32 CDT 2016


Just wanted to quickly throw out that Kotlin's Unit class, their
"equivalent" of void, semantically follows the definition of "type with
only one value" laid out in the enum Void example above.

Dennis

On Sun, Apr 24, 2016, 9:43 PM Brent Royal-Gordon via swift-evolution <
swift-evolution at swift.org> wrote:

> > Some people, including me, argue that Void should be removed altogether,
> because:
> > 1) () is more consistent with curried functions: (Int) -> () -> Double
> > 2) () follows functional programming traditions
> >
> > Now, why don't we repurpose Void to follow functional programming
> traditions as well?
> > Its definition will look like:
> > enum Void { }
> >
> > Basically, Void is a type which cannot have values.
>
> I don't think Void is a good name for this, because it means something
> wildly different from the C-style `void`. It would be a confusing name
> choice for no real reason.
>
> > With it, we can eliminate at least two Swift special cases:
> >
> > 1. Noreturn functions
> >
> > func exit(code: Int = 0) -> Void
> >
> > From this signature, it's obvious that `exit` cannot return normally
> >
> > 2. Rethrows
> >
> > func call<T, U>(block: () throws T -> U) throws T -> U
> >
> > Non-throwing functions are functions throwing Void.
> > So if T=Void, we get the non-throwing version of `call`.
>
> As for these, I think we would actually be better off having a bottom type
> for these use cases. A bottom type is a subtype of all types—sort of the
> opposite of `Any` (which is at the top of the type graph). Since it's
> impossible for any value to belong to all types simultaneously, it's
> impossible to construct a value of the bottom type, so it has the same role
> of meaning "this never returns/happens". But it has an important advantage
> over an empty enum type: you can treat it as any type you'd like.
>
> For instance, suppose we spell the bottom type `_`. Then we can write, for
> instance, this function, which indicates we haven't finished writing
> something:
>
>         func unimplemented(_ description: String, file: String = #file,
> line: String = #line) -> _ {
>                 fatalError("\(description) unimplemented", file: file,
> line: line)
>         }
>
> And use it like so:
>
>         func calculateThing() -> Thing {
>                 if let cachedThing = cachedThing {
>                         return cachedThing
>                 }
>
>                 cachedThing = Thing(foo: calculateFoo(), bar:
> unimplemented("Calculation of bar"))
>                 return cachedThing!
>         }
>
> Because `unimplemented()` returns the bottom type, we can use it anywhere
> in any expression expecting any type, and it will compile just fine,
> implicitly converting to any type the context demands. Of course, since
> there are no values of the bottom type, `unimplemented()` cannot actually
> return a value, and so the call to `Thing.init(foo:bar:)` can never
> actually occur. But from the type checker's perspective, it all works out
> fine.
>
> --
> Brent Royal-Gordon
> Architechies
>
> _______________________________________________
> 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/20160425/d6ebbf7c/attachment.html>


More information about the swift-evolution mailing list