[swift-evolution] Two thoughts on concurrency

Chris Lattner clattner at nondot.org
Thu Aug 24 22:56:56 CDT 2017

On Aug 24, 2017, at 1:59 PM, Dave DeLong via swift-evolution <swift-evolution at swift.org> wrote:
> 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 can’t speak for message/signal, but you need to understand a bit more about how Swift works.  There is a distinction between an actual keyword (which ‘async’ would be, and ‘class’ currently is) and “modifiers”.  Modifiers occur with attributes ahead of a real keyword, but they are not themselves keywords.  They are things like weak, mutating, reliable, distributed, etc.  If we go with the “actor class” and “actor func” approach, then actor would not be a keyword.

> 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?

There is no general rule that can be applied.  Details matter.

> 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.

Sort of, but I see what you’re saying.

> 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.

I understand the conceptual ideal of something being "pure sugar”, but that it is also limiting.  The design as proposed is exactly the opposite of what you suggest: since there are many interesting user facing libraries (future is just one of them) that can be built on top of the primitive language features.

You can still think of the primitives as being built in terms of futures if that makes sense to you, but it isn’t any more correct than it is to say that throws is implemented in terms of a hidden result type.


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

More information about the swift-evolution mailing list