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. 😄
Cheers,
Dave_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution