Here's a neat trick with `async let` I didn't realize. You can use it to avoid blocking on synchronous work.
@mattiem will this still work after the “inherit isolation by default” pitch?

@markmalstrom Hard to say for sure because some details there aren’t finalized yet. But I’m pretty sure yes.

I still find this incredibly verbose though…

@mattiem you find what incredibly verbose?
@markmalstrom So many keywords to express such a straightforward thing!
@mattiem the `async let` keywords or the stuff like `@concurrent` that’s coming with the inherit isolation pitch?
@markmalstrom I’d like a very lightweight way to move synchronous work to the background and await the results. Not quite possible today but I’m getting more hopeful now.
@mattiem I think I’m still a little confused 😅 `async let` seems very lightweight to me. What would you like to change or add?

@markmalstrom I think I want something more like the example at the bottom of this post.

https://forums.swift.org/t/pitch-inherit-isolation-by-default-for-async-functions/74862/119

[Pitch] Inherit isolation by default for async functions

I'm genuinely surpised to hear these suggestions, because my experiences have been exactly the opposite. I haven't yet encountered a situation where I've wanted some kind of stateless background type. But I have regularly found places where I have this one tiny bit of synchronous work that can be expensive and can and should be done off-actor. JSONDecoder is a fantastic, real-world example. This is the critical concept. I was just imagining what would happen if we made this change without t...

Swift Forums
@mattiem ahhh I see, one statement instead of two

@mattiem @markmalstrom

Does this do what you’re wanting? (It wouldn’t have some of the subtler benefits of child tasks, but otherwise I think just adding ‘Task’ and ‘.value’ to that example makes it work.

let result = try await Task {
// this runs on the global executor
try nonIsolatedExpensiveWork()
}.value

@bjhomer @markmalstrom Hmm, I don’t think so. This will inherit the isolation of the calling context, so it will only run on the global executor if that’s already where you are.

@mattiem @markmalstrom I love the easy readability of

let result = try await {
// this runs on the global executor
try nonIsolatedExpensiveWork()
}

Maybe even not so much the executor aspect of it, but just being able to start the async closure straight away like that.

Could the executor be specified similar to what we do with MainActor now? Something like this

await { MainActor in … }

await { GlobalActor in … }

await { CurrentActor in … }

@pasi You can get really close with an immediately-invoked closure today! But what you cannot do is work in the background.

https://mastodon.social/@a_grebenyuk/113206223567233398