> On Aug 20, 2017, at 3:56 PM, Yuta Koshizawa <[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