[swift-evolution] [Concurrency] async/await + actors

Yuta Koshizawa koher at koherent.org
Sun Aug 20 14:56:12 CDT 2017


2017-08-21 2:20 GMT+09:00 John McCall via swift-evolution <
swift-evolution at swift.org>:

> On Aug 19, 2017, at 7:17 PM, Chris Lattner via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> On Aug 19, 2017, at 8:14 AM, Karim Nassar via swift-evolution <
> swift-evolution at 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`.

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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170821/ef1a187b/attachment.html>


More information about the swift-evolution mailing list