Live data from Hacker News

On the proliferation of try, and soon, await (2020)

forums.swift.org

31–40 of 44 posts

Re: On the proliferation of try, and soon, await (2020)

#31
post #15

Are there any popular UI frameworks/architectures that are actually compatible with implicit context switching? I see a lot of desire to purge await from languages but I find the explicit control necessary. What would UI code look like with implicit yields?

C# uses “implicit context switch” on its async/await as it captures the current SynchronizationContext by default. On WPF/winforms/UWP and classic ASP there is one, so unless you other wise tell it, the await always comes back on the UI thread.

Console and ASP net core have null as their SynchronizationContext.

Re: On the proliferation of try, and soon, await (2020)

#32
post #15

Are there any popular UI frameworks/architectures that are actually compatible with implicit context switching? I see a lot of desire to purge await from languages but I find the explicit control necessary. What would UI code look like with implicit yields?

Kotlin is used to write UI code, and potentially-yielding methods are called with ordinary function call syntax. Kotlin does not have the "await" keyword, but it does have an analogue to the "async" keyword, called "suspend". Here is a post from Kotlin's language designer on their philosophy: https://elizarov.medium.com/how-do-you-color-your-functions-...

Kotlin has context blocks instead of the looser context hopping continuation syntax of C# but it seems like it's trading one explicit syntax for another. You can still get off main thread runtime exceptions in Kotlin on Android, so it doesn't solve the issue entirely.

I think that just shows how necessary some kind of explicit syntax is, despite all the talk I see that it's unnecessary. I would love to see more examples though, or a Kotlin native UI.

Re: On the proliferation of try, and soon, await (2020)

#33
post #15

Are there any popular UI frameworks/architectures that are actually compatible with implicit context switching? I see a lot of desire to purge await from languages but I find the explicit control necessary. What would UI code look like with implicit yields?

C# uses “implicit context switch” on its async/await as it captures the current SynchronizationContext by default. On WPF/winforms/UWP and classic ASP there is one, so unless you other wise tell it, the await always comes back on the UI thread. Console and ASP net core have null as their SynchronizationContext.

C# will not context switch until you yield execution with an await. There is some default continuation setup that will happen if you use the Task Parallel Library (where the context management is explicit but abstracted away inside the library) but that's a different thing.

Re: On the proliferation of try, and soon, await (2020)

#34
post #32

Earlier quoted context omitted.

Kotlin is used to write UI code, and potentially-yielding methods are called with ordinary function call syntax. Kotlin does not have the "await" keyword, but it does have an analogue to the "async" keyword, called "suspend". Here is a post from Kotlin's language designer on their philosophy: https://elizarov.medium.com/how-do-you-color-your-functions-...

Kotlin has context blocks instead of the looser context hopping continuation syntax of C# but it seems like it's trading one explicit syntax for another. You can still get off main thread runtime exceptions in Kotlin on Android, so it doesn't solve the issue entirely. I think that just shows how necessary some kind of explicit syntax is, despite all the talk I see that it's unnecessary. I would love to see more examp…

Agreed. The only major language I know of where it's fully implicit is Go, which is rarely used for UI.

> I would love to see more examples though, or a Kotlin native UI.

Jetpack Compose is a Kotlin-native UI framework. Here are some examples of how it uses coroutines: https://developer.android.com/jetpack/compose/kotlin#corouti...

Re: On the proliferation of try, and soon, await (2020)

#35

Earlier quoted context omitted.

What do you think of Java's declared exceptions (or whatever they're called)? They always seemed like a good idea to me, but were ruined by people being lazy or not understanding how to properly design exceptions.

Personal opinion: I think they were a good idea but in practice they don't work great because they try to pretend exceptions work differently from how they really work. They bump up against a reality of exceptions in a bad way: once you have a system for throwing exceptions, the set of types your code must handle becomes fundamentally unbounded because any of your dependencies can change at any time. If there are no…

> "If there are no exceptions and you have a function-call control flow, you can enforce that the only types the caller understands from the callee are the types in the signature."

This has historically resulted in either ignoring errors from sub-functions, because their error return type don't map properly, or returning generic "i got an error" without any more information about what the error was.

And all this was historically patched over by having verbose log files that could be written to from anywhere and the user had to peruse and try to make sense of after the fact.

Some franework tried to create complicated error code (like Windows COM) but in the end there is no free lunch. Errors are hard.

Re: On the proliferation of try, and soon, await (2020)

#36
post #22

It's important to distinguish: asset1 = await httpGET(...) asset2 = await httpGET(...) from: assets = await Promise.join(httpGET(...), httpGET(...)) asset1 = assets[0] asset2 = assets[1] Where the first does one request and doesn't start the next until the previous had completed, and the second does them concurrently. BUT - you could have a language where async functions are awaited by default, and you'd have to writ…

Or you can have a language where the implied `await` is delayed until the information is used, but the initiation starts as soon as the information required to initiate is ready:

  asset1 = httpGET(...)
  asset2 = httpGET(...)

  doSomethingWith(asset1)
  doSomethingWith(asset2)
No problem, both requests concurrent, don't have to think about it. They will probably be neatly batched by the executor into a single outgoing TCP packet too.

  asset1 = httpGET(...)
  asset2 = httpGET(functionOf(asset1))

  doSomethingWith(asset2)
Second request has to wait until the first has completed, because this is correct. It can't be started until the first is completed.

Re: On the proliferation of try, and soon, await (2020)

#37
post #24
post #22

It's important to distinguish: asset1 = await httpGET(...) asset2 = await httpGET(...) from: assets = await Promise.join(httpGET(...), httpGET(...)) asset1 = assets[0] asset2 = assets[1] Where the first does one request and doesn't start the next until the previous had completed, and the second does them concurrently. BUT - you could have a language where async functions are awaited by default, and you'd have to writ…

> Presence of an 'async' decorator on functions isn't strictly needed, but does convey extra information in the API, which is useful. I disagree. It's akin to having a `gc` decorator on a function that uses GC. Maybe useful for C++, but not useful for high-level languages like Java, Swift, Go, JavaScript, Python. Long-term, I firmly believe `async` will reveal itself to be a mistake. It's simply unwillingness by lang…

> unwillingness by language designers (or more likely implementors) to treat threading like GC

There is a technical reason behind this, it's not just style.

The async-await transformation is highly compatible with calling other things in the C environment and receiving callbacks from that environment.

In some implementations the async-await transformation converts nested async functions to stackless state machines that are compatible with the C environment assumed by other libraries (especially in other languages) and by the operating system.

But it does have some performance cost, compared with functions that can assume stack scope. That cost only appears when using functions labelled "async".

Making every function automatically async in this model is nicer syntax (imho) but adds that cost to every function, unless the compiler is able to do a more global analysis, or deviates from strong compatibility with the C environment.

Another approach is to transform them to system threads. Then you don't need the async-await transform and it's compatible with the C environment, but you lose performance in some types of program where async-await is used, and sometimes a lot of memory or address space. So there's still a cost. Especially on targets where threads aren't particularly well implemented.

Yet another is green threads or other C-compatible coroutine implementation. This costs some compatibility with the C environment on some targets, though. Switching stacks in C works almost everywhere, but not everywhere, and has portability issues. The standard library function to assist with stack switching has been removed from POSIX, but it was never particularly fast anyway.

Go gets around this by being willing to deviate more from the C environment. It goes hand in hand with the very self-contained nature of Go compiled programs. Java gets around this by being a JIT interpreter which is free to do a lot of things its own way inside the Java execution.

Re: On the proliferation of try, and soon, await (2020)

#38

The original poster says that these functions can't ever have invariants broken: > Functions that only mutate instances of well-encapsulated types through their public APIs. That includes nearly all functions that are not methods. > Methods of well-encapsulated types that only mutate non-member instances of other well-encapsulated types through their public APIs. This is incorrect! Consider the following function (in…

[deleted]

Re: On the proliferation of try, and soon, await (2020)

#39
post #30
post #24

Earlier quoted context omitted.

> Presence of an 'async' decorator on functions isn't strictly needed, but does convey extra information in the API, which is useful. I disagree. It's akin to having a `gc` decorator on a function that uses GC. Maybe useful for C++, but not useful for high-level languages like Java, Swift, Go, JavaScript, Python. Long-term, I firmly believe `async` will reveal itself to be a mistake. It's simply unwillingness by lang…

I believe if you read far enough in the thread you’ll see Swift’s “Structured Concurrency” proposal does the same thing. In Go you must `go ...` to invoke concurrency. In Swift that would be `async let = ...` under the proposal (which has already been implemented) on main. `async` just says this function returns a “future” and `await` just desugars the future. I prefer Rust’s approach where the future is an actual ty…

Indeed, async let seems like a massive improvement! (Judging by this proposal [1].) Still the wrong default IMO (should be `let x = async ...` so that you can then do `let xs = [async f(), async g()]`) but definitely a step in the right direction.

Now just remove `async` and `throws` function annotations and/or make those default, and all noise will be removed!

[1] https://github.com/apple/swift-evolution/blob/main/proposals...

Re: On the proliferation of try, and soon, await (2020)

#40
post #15

Are there any popular UI frameworks/architectures that are actually compatible with implicit context switching? I see a lot of desire to purge await from languages but I find the explicit control necessary. What would UI code look like with implicit yields?

C# uses “implicit context switch” on its async/await as it captures the current SynchronizationContext by default. On WPF/winforms/UWP and classic ASP there is one, so unless you other wise tell it, the await always comes back on the UI thread. Console and ASP net core have null as their SynchronizationContext.

> it captures the current SynchronizationContext by default.

Which results in the majority of async code, which doesn't run in a UI context, needing to spam `.ConfigureAwait(false)` everywhere. It's the most visible wart in C# today - and no end of requests for a more succint alternative: https://github.com/dotnet/csharplang/discussions/645

Post reply on HN