[swift-evolution] [Concurrency] do async

John McCall rjmccall at apple.com
Wed Aug 23 12:22:30 CDT 2017


> On Aug 23, 2017, at 1:16 PM, Joe Groff via swift-evolution <swift-evolution at swift.org> wrote:
> 
>> 
>> On Aug 21, 2017, at 11:23 PM, Jonathan Hull via swift-evolution <swift-evolution at swift.org> wrote:
>> 
>> I have seen a lot of examples which use both do and beginAsync:
>> 
>> 	beginAsync {
>> 		do {
>> 			try await foo()
>> 		} catch let e {
>> 			//Handle Error
>> 		}
>> 	}
>> 
>> I twitch every time I see this, because I thought part of the point of this was to avoid pyramiding.  It would seem to be an argument for combining try and await, but as others have pointed out, that causes issues with try? and try!.  I also really like the explicitness of knowing what could actually throw errors.
>> 
>> I propose that we instead combine do and beginAsync.  There are 3 cases:
>> 
>> 
>> 1) Just throws (i.e what we have now):
>> 
>> 	do {
>> 		try foo()
>> 	} catch let e {
>> 		//Handle Error
>> 	}
>> 
>> 
>> 2) Just async (no catch needed):
>> 
>> 	do async {
>> 		await foo()
>> 	}
>> 
>> 
>> 3) Both throws and async:
>> 
>> 	do async {
>> 		try await foo()
>> 	}catch let e{
>> 		//It would be a compiler error not to have a catch statement when there is a try in the do block.
>> 	}
>> 
>> 
>> This feels much less messy to me, and will avoid unnecessary pyramids while still allowing throws and async to be separately declared.
>> 
>> Thanks,
>> Jon
> 
> The proposal is perhaps a bit beginAsync-heavy because it puts a lot of attention on how to adapt existing frameworks to work with coroutines. My feeling is that, in a system with frameworks that have more fully adopted coroutines in all the appropriate places, that you won't need to explicitly enter an async context as frequently since more contexts will already be `async` where they need to be, and that in the situations where you do need to enter a new async context, raw `beginAsync` won't be the best way to do so. `beginAsync` is still going to begin its coroutine body immediately on the current thread, but you're likely to want to associate it with a specific context using something like a version of dispatch_async that takes a `() async -> ()` block. There are also APIs that could provide for coordination with the coroutine, such as a constructor for Future<T> that takes an () async -> T block which is automatically fulfilled by the completion of the block. I'm not against the idea of providing language sugar to make working with coroutines nicer (that is, after all, their whole reason to exist!), but I'm not sure this is the right thing to sugar, and we can always add sugar later once the core language model is set.

Right.  I would only add to this that I'm specifically worried about adding features that make blocking the current thread more sugared.

John.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170823/5bd777a7/attachment.html>


More information about the swift-evolution mailing list