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

Reply via email to