Thought about it in more depth, and I’m now firmly in the camp of:
‘throws’/‘try' and ‘async’/‘await' should be orthogonal features. I think the
slight call-site reduction in typed characters ('try await’ vs ‘await’) is
heavily outweighed by the loss of clarity on all the edge cases.
—Karim
> On Aug 21, 2017, at 1:56 PM, John McCall <[email protected]> wrote:
>
>>
>> On Aug 20, 2017, at 3:56 PM, Yuta Koshizawa <[email protected]
>> <mailto:[email protected]>> wrote:
>>
>> 2017-08-21 2:20 GMT+09:00 John McCall via swift-evolution
>> <[email protected] <mailto:[email protected]>>:
>>> On Aug 19, 2017, at 7:17 PM, Chris Lattner via swift-evolution
>>> <[email protected] <mailto:[email protected]>> wrote:
>>>> On Aug 19, 2017, at 8:14 AM, Karim Nassar via swift-evolution
>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>
>>>> This looks fantastic. Can’t wait (heh) for async/await to land, and the
>>>> Actors pattern looks really compelling.
>>>>
>>>> One thought that occurred to me reading through the section of the
>>>> "async/await" proposal on whether async implies throws:
>>>>
>>>> If ‘async' implies ‘throws' and therefore ‘await' implies ‘try’, if we
>>>> want to suppress the catch block with ?/!, does that mean we do it on the
>>>> ‘await’ ?
>>>>
>>>> guard let foo = await? getAFoo() else { … }
>>>
>>> Interesting question, I’d lean towards “no, we don’t want await? and
>>> await!”. My sense is that the try? and try! forms are only occasionally
>>> used, and await? implies heavily that the optional behavior has something
>>> to do with the async, not with the try. I think it would be ok to have to
>>> write “try? await foo()” in the case that you’d want the thrown error to
>>> turn into an optional. That would be nice and explicit.
>>
>> try? and try! are quite common from what I've seen.
>>
>> As analogous to `throws` and `try`, I think we have an option that `await!`
>> means blocking.
>>
>> First, if we introduce something like `do/catch` for `async/await`, I think
>> it should be for blocking. For example:
>>
>> ```
>> do {
>> return await foo()
>> } block
>> ```
>>
>> It is consistent with `do/try/catch` because it should allow to return a
>> value from inside `do` blocks for an analogy of `throws/try`.
>>
>> ```
>> // `throws/try`
>> func foo() -> Int {
>> do {
>> return try bar()
>> } catch {
>> ...
>> }
>> }
>>
>> // `async/await`
>> func foo() -> Int {
>> do {
>> return await bar()
>> } block
>> }
>> ```
>>
>> And `try!` is similar to `do/try/catch`.
>>
>> ```
>> // `try!`
>> let x = try! foo()
>> // uses `x` here
>>
>> // `do/try/catch`
>> do {
>> let x = try foo()
>> // uses `x` here
>> } catch {
>> fatalError()
>> }
>> ```
>>
>> If `try!` is a sugar of `do/try/catch`, it also seems natural that `await!`
>> is a sugar of `do/await/block`. However, currently all `!` in Swift are
>> related to a logic failure. So I think using `!` for blocking is not so
>> natural in point of view of symbology.
>>
>> Anyway, I think it is valuable to think about what `do` blocks for
>> `async/await` mean. It is also interesting that thinking about combinations
>> of `catch` and `block` for `async throws` functions: e.g. If only `block`,
>> the enclosing function should be `throws`.
>
> Personally, I think these sources of confusion are a good reason to keep the
> feature separate.
>
> The idea of using await! to block a thread is interesting but, as you say,
> does not fit with the general meaning of ! for logic errors. I think it's
> fine to just have an API to block waiting for an async operation, and we can
> choose the name carefully to call out the danger of deadlocks.
>
> John.
>
>>
>> That aside, I think `try!` is not so occasional and is so important. Static
>> typing has limitations. For example, even if we has a text field which
>> allows to input only numbers, we still get an input value as a string and
>> parsing it may fail on its type though it actually never fails. If we did
>> not have easy ways to convert such a simple domain error or a recoverable
>> error to a logic failure, people would start ignoring them as we has seen in
>> Java by `catch(Exception e) {}`. Now we have `JSONDecoder` and we will see
>> much more `try!` for bundled JSON files in apps or generated JSONs by code,
>> for which decoding fails as a logic failure.
>>
>> --
>> Yuta
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution