[swift-evolution] Two thoughts on concurrency

Dave DeLong delong at apple.com
Thu Aug 24 15:59:04 CDT 2017

Hi everyone,

(the standard disclaimer of “I’m neither a compiler engineer nor a language design expert” applies)

I’ve been trying to keep up with all the discussion around concurrency going on, and I’m admittedly not very familiar with async/await or the actor pattern.

However, a couple of things worry me about the direction the conversation seems to be going:

Keyword Explosion

During the Great Access Control Wars of Swift 4, one of the points that kept coming up was the reluctance to introduce a bazillion new keywords to address all the cases that were being brought up. The impression I got is that adding new keywords was essentially an anti-pattern. And so when I’m reading through this onslaught of emails, I’m troubled by how everything is seeming to require new keywords. There’s the obvious async/await, but there’s also been discussion of actor, reliable, distributed, behavior, message, and signal (and I’ve probably missed others).

I’m not opposed to adding new keywords by any means, but can we get some clarification on some limits of reasonableness? What restraint (if any) should we be exercising as we consider this feature?

Language vs Library Feature

Related to the explosion of keywords is the question of whether the concurrency model is going to be a language feature or a library feature. Allow me to explain…

We currently have language support for errors with throws and try (and friends):

func doSomething() throws → Value { … }

let value = try doSomething()

However, this could be viewed as sugar syntax for a hypothetical library feature involving a Result<T, Error> type:

func doSomething() → Result<Value, Error> { … }

let value = doSomething().value! // or however you get the value of a Result

In other words, throws and try are the language support for silently hiding a Result<T, Error> type.

I would be really happy if whatever concurrency model we end up with ends up being sugar syntax for a library feature, such that async and await (or whatever we decide on) become sugar for dealing with a Future<T> type or whatever. Implementing concurrency in this manner would free app developers to handle concurrency in the manner in which they’re familiar. If you wanted, you call the function without await and get back the underlying Future<T>. async becomes sugar for simplifying the return type, like in the throws example above. try await becomes sugar for fulfilling the promise or dealing with a cancellation (or other) error, etc.

In other words:

async func doSomething() → Value { … }

Let value = await doSomething()

Becomes sugar for this pseudocode:

func doSomething() → Future<Value> { … }

let value = doSomething().value // or however you “wait” for the value

(Incidentally, I would love to see this pattern retroactively applied for throws and errors)

Please don’t all break out your pitchforks at once. 😄 


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170824/9fdcc2d6/attachment.html>

More information about the swift-evolution mailing list