> On Aug 20, 2017, at 3:56 PM, Yuta Koshizawa <ko...@koherent.org> wrote: > > 2017-08-21 2:20 GMT+09:00 John McCall via swift-evolution > <swift-evolution@swift.org <mailto:swift-evolution@swift.org>>: >> On Aug 19, 2017, at 7:17 PM, Chris Lattner via swift-evolution >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >>> On Aug 19, 2017, at 8:14 AM, Karim Nassar via swift-evolution >>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> 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 swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution