Empower Apps

Matt Massicotte from Chime talks about the challenges he faced migrating the Async/Await and some misconceptions folks might have with asynchronous programming.

Guest

Related Links 

Related Links 

Social Media

Email
leo@brightdigit.com
GitHub - @brightdigit

Twitter
BrightDigit - @brightdigit

Leo - @leogdion

LinkedIn
BrightDigit

Leo

Instagram - @brightdigit
Patreon - empowerappshow

Credits

Music from https://filmmusic.io
"Blippy Trance" by Kevin MacLeod (https://incompetech.com)
License: CC BY (http://creativecommons.org/licenses/by/4.0/)
  • (00:00) - What's (Not) New with ExtensionKit
  • (03:06) - Migrating to Async/Await
  • (10:59) - Dealing with Older APIs
  • (12:46) - On Swift 6
  • (18:59) - Locks and Semaphore
  • (24:48) - Swift Proposals
  • (27:31) - WWDC 2023
Thanks to our monthly supporters
  • Bertram Eber
  • Edward Sanchez
  • Satoshi Mitsumori
  • Steven Lipton
★ Support this podcast on Patreon ★

Creators & Guests

Host
Leo Dion
Swift developer for Apple devices and more; Founder of BrightDigit; husband and father of 6 adorable kids
Guest
Matt Massicotte
swift ⌨️, outdoors 🏔, justice ⚖️ | @chimehq, prev: @crashlytics, @apple

What is Empower Apps?

An exploration of Apple business news and technology. We talk about how businesses can use new technology to empower their business and employees, from Leo Dion, founder of BrightDigit.

Leo Dion (host): Welcome to
another episode of Empower Apps.

I'm your host, Leo Dion.

Today, I'm joined by
Matt Massacott again.

Matt, thank you so much for
coming back on the show.

Matt Massicote (guest):
I'm happy to be here.

Thanks for having me.

Leo Dion (host): Before we get into your
upcoming presentation at Swift Toronto.

Go ahead and I'll let you
introduce yourself and chime.

Matt Massicote (guest): Sure.

Well, my name is Matt.

I'm a longtime macOS developer.

I've done a little bit of
iOS, but not that much.

I put some time in at Apple, working on
iOS actually and then ended up working

independently and so I'm like a part
time independent developer right now.

And one of the main projects
I work on is called Chime,

which is a like lightweight
minimalistic editor for the Mac.

Leo Dion (host): And we had you on,
was it last year or a year and a

half ago to talk about extension kit?

Matt Massicote (guest): yeah, yeah,
it was right about a year ago.

And it's funny.

Leo Dion (host): go ahead.

Matt Massicote (guest): It's funny
because I don't remember where I was in

my extension kit journey when we talked.

But all the stuff that's come up for
my work on concurrency started there.

Leo Dion (host): Okay before we
get into that, I do want to ask did

anything happen with Extension Kit since
DubDub, and as far as Extension Kit

is concerned, like, how's that going,
outside of what we'll talk about today?

Matt Massicote (guest): I would, I would
love to sit down with somebody who works

on extension kit at Apple and just hear
the story about what is going on there

because they just to remind people.

So it was introduced.

Last year with absolutely
no mention at all during

Leo Dion (host): talks.

Yeah,

Matt Massicote (guest): Yeah, no,
nothing, which is really unusual.

Additionally, it's a weird
thing to add to Mac OS, right?

Because almost all of it, almost all
the features that it provides were

technically possible before they
were extension kit makes it easier,

but loading code as plugins is all
things that you could do before.

So the end parts of extension kits.

Are, and to this day,
still exposed on iOS.

So it was a weird, it was a weird thing.

And it really felt to me it
was supposed to launch for iOS.

Got pulled at the last minute,
that's why we saw no video about it.

And they just kinda let
it sit, until this year.

And then so this coming up year, I
was convinced, 100% convinced, that

it was gonna be released for iOS.

And what's weird is, more of it was
added, more API was added to iOS.

But still not enough to actually use it.

And there was also no videos about it.

Leo Dion (host): How about Mac OS?

Anything different there?

Matt Massicote (guest): No,
it's basically the same.

Leo Dion (host): Okay.

Interesting.

Matt Massicote (guest): Yeah.

So something funny is going on.

Leo Dion (host): Yeah, yeah, yeah.

Is it only available on Mac OS?

So, no vision, no watch, no TV.

Matt Massicote (guest):
vision OS is the same.

No watch, but vision OS and iOS and, and
well, iPad, it's the same thing where

there's portions of it are available on
iOS, but not enough to actually use it.

Leo Dion (host): Okay.

Matt Massicote (guest): Just bizarre.

Leo Dion (host): we'll put
links to our previous episode.

I'm definitely interested in jumping
into it once I get farther with Bushel.

But, yeah, it's, it's interesting.

So it sounds like...

Your work in extension kit, you
found out a few little quirks with

async await specifically you want
to give just the big picture of

what kind of issues you've run into.

Matt Massicote (guest): Yes, absolutely.

Well, so it started with
my work on extension kit.

Part of the idea here is
you build an API that other

developers are going to use.

And it's this public API that
you publish as part of your

extension kit, SDK, however
you're going to package it up.

And so I thought, well, if I'm
going to do this, I might as well

be as forward looking as possible.

At the time, I hadn't looked at
concurrency at all, but I thought

this is a great opportunity.

I'm going to dive in here and I'm
going to see if I can make it work.

And at the beginning, that
seemed like a wonderful idea.

It was, it's felt easy.

It felt like you're just getting rid of
completion of completion handlers and

replacing them with the async keyword.

Like it felt really nice.

And I got pretty far with it.

The integration with Chime is also
probably uncharacteristically deep.

I would imagine that most people
that are going to be using extension

kit, it's going to be a small
feature that you're going to expose.

But with QIIME, it just
made a lot of sense.

So it's very deeply integrated
into the application, used all

over the place, everywhere.

And so it impacted pretty much
everything about how the app works.

And that meant that concurrency
started, it's a little bit viral.

And so it started getting it working its
way into more parts of the application.

And I think the first thing that
really hit me when I started

realizing, okay, I don't know if
I know what I'm doing is I started

seeing really terrible race conditions
where I would have like these events

happening ABC, but, but what would
be happening in the extension would

be, they would not be in that order.

Leo Dion (host): Hmm.

Okay.

Matt Massicote (guest): And at
first I was like deeply confused by

this, but after I started looking
into it, I realized that it makes

everything makes total sense.

What was happening, what was
going on here was I was just

putting these unstructured tasks.

To start running, to get,
to get an async context.

And I think this is a thing a lot
of people will do, is that apps

fundamentally, they start with one
thread, one main, one main, I mean

actor, but one main thread, and
eventually they're going to start

running stuff, and they need some
sort of async context to do that.

And so in many cases, And if you look
at, you'll see blog posts all over

the place saying concurrency is easy.

And if you don't have an async context,
you just use a task and you're done.

And that is technically true, but tasks
don't synchronize across each other.

So you can make them synchronized.

You can start task A and then wait
inside of task B for task A to be done.

That's totally allowed.

That's the way you do it.

Leo Dion (host): Mhm.

Matt Massicote (guest): But if you don't
establish these explicit dependencies

across tasks, they run in any order.

There's absolutely no dependency
enforced by the system at all.

And so this is where I first started
running into problems is because

I was introducing concurrency in
this fundamental part of my app,

but they were not really connected
inside of the app structure.

So there's one call over here
and then many, many, many, many,

many layers and APIs distant from
that place, there'd be another

async call that I needed to make.

And previously, those
were completion handlers.

They would start, run a bunch of code,
and then this one would start and they

would always start one after another.

And replacing those calls, those
completion based calls with

tasks meant that that ordering
was no longer being enforced.

And that's really the fundamental
thing that I was running into,

Leo Dion (host): That.

Okay.

I'm gonna, I'm gonna.

Don't take this the wrong way, but
that sounds like a feature, not a bug.

Matt Massicote (guest): Being ordered.

Leo Dion (host): yeah, because yeah,
that's where you're kind of like, for

me, an async task would be something
you just run whenever you want to,

and it has no dependencies per se.

But what it sounds like here is is you
need to set up some sort of it sounds

like a use case for an actor where you
have one central lane where things are

run and it can only be run on that lane.

Is that correct?

Matt Massicote (guest): actually,
no, but that's a very, that, that

makes sense what you're saying.

And you're right, it's not a
bug, it's a, what this is, is an

implication of changing from completion
based systems to async systems.

Leo Dion (host): right, right,

Matt Massicote (guest): And so the
implication, and it's like, took me

a super long time to actually even
understand, like, what is going on here.

And the reason is that a completion
based system has, you call it

synchronously, and then it will
do its work internally, it'll

do its work asynchronously.

And an async based system cannot,
it is impossible to do that

with an async based system.

The caller is the one who's
responsible for coordinating these

Leo Dion (host): right, right, right,

Matt Massicote (guest): You might have
some nice object that has a whole bunch

of completion handler based blocks, and
internally, it's got its own dispatch

queue, and when you make a call, it
synchronizes everything internally.

And that is no longer possible to do.

That pattern is not possible
to do with Swift concurrency.

Leo Dion (host): right, right.

So you're sa

Matt Massicote (guest): not supported

Leo Dion (host): so you were saying
actors are not what you want.

Can you explain that a little bit more?

Matt Massicote (guest): because you
have to use the async keyword as

soon as you use the as soon as you
introduce a wait It's up to the caller

that writes a wait to do the ordering
actors cannot internalize that stuff

and you might and at first you might
Think oh, of course they could because

you just put the queue inside of the
actor and that's true You can put

the queue inside of the actor, but
you no longer have the ability to

serialize Putting stuff in that queue.

That's up to callers.

And so this is like
this fundamental change.

I think a lot of people are very
used to, I certainly was, used

to writing code this way, and
you just can't do that anymore.

When you're going into concurrent.

Leo Dion (host): okay.

So what did you end up
doing to get around that?

Matt Massicote (guest): Well, first I
would say I swore a whole bunch, and

then figured out what the problem was.

It took me a long time to even
understand the problem, but

once I got it, what I ended up
doing was introducing a queue.

Like, fundamentally, you need a queue.

There are many problems, many,
any, pretty much any time you have

a stateful system, you have to be
able to serialize these things.

And so I had to introduce a queue.

But I had this problem because I
had a whole bunch of legacy code and

I could have like spawned task A.

Up at the top, grabbed grabbed it in
a variable and then passed it through

all these callers to the spot where I
called task B that would have worked.

But it was just so awkward.

And so it was just totally
unwieldy to do that.

So what I did was I
introduced a global queue.

So one queue for the entire application.

And I could submit, instead of just
standalone tasks, I would make a,

make a task, that task, and then
put it into this global queue.

Leo Dion (host): Okay.

Matt Massicote (guest): And that
was my, I suppose I would call

that my my stopgap solution.

That enabled me to remove
all the race conditions.

It's gross, but it was possible to do.

Leo Dion (host): What if, like, what
other people, what, what if other

people, what if you found other
people are doing online for what

you're particularly running into here?

Matt Massicote (guest): I have not
found anybody really talking about

this exact kind of problem in this way.

I think people have noticed the ordering
problem of a standalone unstructured

task is very well understood.

And you said, it's not
a bug, it's a feature.

And you're right, that is
how it's supposed to work.

But I think that when you start
introducing concurrency, With stateful

systems into existing applications.

That's the only time these kinds of
things are really going to come up.

Leo Dion (host): yeah, and it's
I think that's the key is like

stateful right where it's like Oh,
you need to know when something

is ready and then run the task

Matt Massicote (guest): right?

Absolutely.

That's the critical component
of, I think many people have been

introducing concurrency into their
apps, using things like the SwiftUI.

task, and they're probably loading
code, not loading code, loading

data from some remote from stateful.

Leo Dion (host): Right, right.

Yeah.

What I wanted to jump in and talk a
little bit more about you mentioned

some like older APIs that you're
running into were any of those

running into issues with async await?

Now I'll, I'll just preface by saying
I've run into issues with like NS

operation, like maintaining some
old code that uses NS operation.

And then we want to do async await.

And it's like, Oh yeah, there's like all
sorts of issues with older objective C

APIs once you start doing async await,
did you run into anything like that?

Matt Massicote (guest): I'm very
curious what your problem was,

but first I'll say I totally did.

So, I think that the, my first
realization along this journey was

that I didn't really understand
how to establish asynchronous

contexts in a way that would let me
do the things I was already doing.

That was like one big realization.

But then the second really
important realization was All the

warnings are turned off by default.

And so what I was doing, was I was
making an API that was inherently

async, but I was, because there was
no warnings, I didn't understand

how to do that correctly.

Leo Dion (host): Okay.

Matt Massicote (guest): And so once I
started realizing, okay, in order to do

this, I have to turn on these warnings,
turned on these warnings I had built an

API that was fundamentally incompatible.

And then what does that even mean?

And it could be what you're talking
about is if you have an async function,

it needs to be either accepting sendable
stuff or it needs to be both accepting

sendable stuff and returning sendable
things or isolated to a global actor.

And you have no other alternative.

That is it.

Leo Dion (host): Right.

Right.

Mm hmm.

Matt Massicote (guest):
And so what's interesting.

So two things I have
noticed existing APIs.

One is apple.

I think many people on apple
in apple internally did not

realize this was the case.

Leo Dion (host): Mm

Matt Massicote (guest): And so apple has
shipped a few APIs that don't pass these

warnings, but they are explicitly async.

Leo Dion (host): Yeah.

Matt Massicote (guest): like one
example I'll give that I just happened

to notice was it's in HealthKit.

It was like a HealthKit, I can't
remember if it's called Query,

but it's called an async query.

And it is specifically built to allow
you to use concurrency both accepted

and returned non sendable stuff.

So whoever made this did not
understand that that was, that

was an impossible API to build.

Leo Dion (host): Yeah.

And I think that's a big, like, that's
a big Swift 6 thing is like, all

that stuff has to be fixed by then.

Matt Massicote (guest): Right.

But now, so the health kit
team had this problem, right?

Because, because they ship this API,
they, they must either make the HK

health store, I think it's called.

And they must make that sendable as
well as the return value, or they were

going to have to deprecate this API.

Cause if they couldn't make
them sendable, this API

can never be made to work.

Well, I suppose

Leo Dion (host): isn't there like
an attribute where it can basically

say, Oh yeah, it's sendable, don't
worry about it, and you don't

Matt Massicote (guest): has to
actually be sendable, but yes, yes,

Leo Dion (host): Okay.

Okay.

Matt Massicote (guest): You're right.

I suppose the other, other alternative
and one that I have used a lot

is you just can't use this on
anything other than a global actor.

Leo Dion (host): Yeah.

Matt Massicote (guest): hammer
that you can use that you can

always put things onto your own
global actors onto the main actor.

And that is necessary in many cases

Leo Dion (host): so we healthcare,
were there any other APIs you ran into

like any app kit stuff or anything like

Matt Massicote (guest):
well, extension kit.

Leo Dion (host): Okay.

Matt Massicote (guest):
so, and widget kit.

So the, so examples of these
things are, these are APIs where.

It's probably supposed to be main actor
isolated and by all accounts, by how

you're understanding how the API is
work, it really should be, but Apple

has not done that annotation yet.

Leo Dion (host): I want to say like,
if you do any of the new stuff in,

in Xcode 15 beta, everything is like
automatically main actored for you.

Oh, really?

Matt Massicote (guest): Yeah.

So both extension kit and
widget kit are still not fixed.

And so they're impossible
to use without warnings.

Leo Dion (host): Okay.

I know SwiftUI, I used to have
to put everything in a main

actor for UI changes for obvious
reasons, but now, like, they

automatically do that for you.

So,

Matt Massicote (guest): Yeah.

You know, there's a really
strange Swift UI in particular.

There's a really strange behavior.

I'm going to mix up which one it is off
the top of my head, but there are, it's

possible for property wrappers, which
is used all over the place in Swift UI

to implicitly impose actor isolation.

So this is the thing that trips up so
many people cause they don't understand.

They're like, if I remove an at state
object, everything, if I, if I leave in

the at state object, everything works.

And if I remove it, all of a sudden
I'm getting warnings about not being on

the main actor, what's going on here.

And the reason is that as of right
now, property wrappers can change the

actor ness of the type that uses them.

Leo Dion (host): Well, I'm wondering,
too, like, you can put, you can

say something as main actor on a
protocol, and then if you're putting

all sorts of semantic sugar, like,
macros, if it's automatically

putting that in there for you, too.

Because I've been doing a lot more
observation stuff, and less, like, the

Matt Massicote (guest):
that is possible also.

But I can tell you that they're
going to remove that behavior.

So the behavior of protocol of
excuse me, of property wrappers,

changing actor ness of types is

Leo Dion (host): Okay.

Okay.

Matt Massicote (guest): because
it just, it's confusing everybody.

And so that's, you might need to
start putting more at main actors

on your types because of that.

Leo Dion (host): Yeah.

Yeah.

Yeah.

Yeah.

And that's, I've, so going back to
what you were talking about, about like

sendable and stuff, there's like, at
least as far as an Xcode and in the

Swift package, you can, you can turn
those flags on and, Man, like, yeah,

I've run into, so there's all sorts
of actor stuff you have to add for

Swift 6, there's every protocol now
requires any keyword, like, it's crazy

how much stuff and it's understandable
why we haven't seen Swift 6 being ready

yet after, after dub dub, so, yeah.

Matt Massicote (guest): know, I, so I
think that, and I'm going to make this

prediction in my talk, but I think
that's probably going to be the theme.

I think, I think that Swift 6 is going
to be rough because I think there are

Leo Dion (host): I think it's going to
be the roughest since, whatever, SWF3

or SWF4, whenever we got ABI Stability.

It's been a while since we've had any
rough upgrades in SWF, so yeah, I agree.

Matt Massicote (guest):
going to be even rougher.

I think it's going to
be the worst one yet.

Yeah.

And the reason because, and I'm just
using my experience as an example is

that I built an API that can never be,
it was using async await everywhere

and it can never work impossible.

And I needed to change the API.

That API was unsupportable.

And so, there are, I'm sure there
are people right now that are

building their apps happily building
async await everywhere into their

app in a way that will never
be compatible with concurrency.

And once those war so, and so this
is really weird because Apple went

from optional warnings to errors.

This is, this is a
mistake in my opinion.

Leo Dion (host): well and I it's
gonna take a while I feel like it's

gonna take a while like I wouldn't
be surprised if Swissx isn't even

ready for dub dub 24 at this point Cuz

Matt Massicote (guest): That's possible.

Leo Dion (host): like we like you
said, I don't feel like it seems

weird to go from optional warning
to error to error I think at some

point maybe in the next year.

We'll see an Xcode release where
Those are gonna become actual warnings

Matt Massicote (guest): Yeah, and
I think that if you are using, if

you are using concurrency and don't
have complete turned on, not just

targeted, but complete, You're opening
yourself up, you're opening yourself

up to some really serious pain.

Because if you are building a system
that cannot be compatible with this,

what are you going to do at that point?

And I think you want to know that now.

So you want to have those warnings
turned on, so you know right away at the

beginning, Oh, I'm building something,
but it's actually harder than I

Leo Dion (host): yeah.

And I'll I have a good blog post, I
forgot who it was, who showed you how

to turn those warnings on for Swift
6, and I'll put that in the show

notes because it's really helpful.

Do you want to talk about well, one
of the questions I had, do you miss

anything regarding dispatch queue?

It sounds like you do miss a lot as
far as dispatch queue, is that correct?

Matt Massicote (guest): I mean, I don't
know if miss is the right terminology.

Leo Dion (host): Yeah, I know.

I know.

Matt Massicote (guest): I, I think that
I don't think that for, I'm talking

about for like complex use cases, I
would be surprised if you can get away

with using a concurrency in complex
ways without using a current concurrency

compatible lock and or queue.

I think it's possible.

I think some apps can do it, but I, but
I, boy, I think you'll have a hard time.

I mean,

Leo Dion (host): You keep saying this
stuff and I'm like, why, why not actors?

What's wrong with actors?

Isn't that kind of
what it's fundamentally

Matt Massicote (guest):
that's a great question.

That's a great question.

So, what are actors for?

So actors protect mutable state,

Leo Dion (host): Okay.

Matt Massicote (guest): they, what
they cannot do is they cannot control

ordering of access to that state.

So actors are

Leo Dion (host): they can, but they're
specifically for race conditions, right?

So you could, you're like,

when you talk about a lock, like it's
essentially what an actor is for, right?

Matt Massicote (guest): yeah.

So the lock is about re entrancy.

So actors are re entrant, which
means that the same object so

that you can get the call into
the same method multiple times,

Leo Dion (host): Yeah.

Matt Massicote (guest): more than one
thread can be running inside of an

actor, isolated method at the same time.

Leo Dion (host): Say that one more time.

Matt Massicote (guest): So more than
one thread, more than one thread

can be inside, running inside of it.

So, take a really,
really simple example.

Imagine you have a little cache,
where you want to be able to like

reach out to some service, and it
takes a long time to get that value,

so you want to cache it in an actor.

Leo Dion (host): Okay.

Matt Massicote (guest): So you're
probably going to do some little check

if the value is op it's optional and
if the value is there, I'm going to

return it, and if not, I'm going to
go do this await, and I'm going to get

it, and then I'm going to return it.

This is like a really classic
caching pattern, I hope you're

following what I'm talking about.

That doesn't work with an actor.

Even something like that does not work
with an actor, because between the

check and the await call, another object
can come in and make that call again.

Leo Dion (host): See my thought, my
whole idea with actor was that like

it's basically a way to make sure
that somebody can't like two people,

two people, two, two threads can't do
something to an actor at the same time.

Like I thought it was kind of
like that where it was like

essentially a cue where it's like

Matt Massicote (guest): You know what?

In a lot of ways, it is
exactly like a dispatch queue.

But the problem with, and it's the
same kinds of problems with dispatch

queues, where the dispatch queue,
the body of the queue is synchronous.

Leo Dion (host): right.

Matt Massicote (guest): So, and
the same, it's the same kind of

thing with an actor, is that the
synchronous code, yes, is serial,

and only one thread can be running
in the synchronous code at one time.

But as soon as you put an
await in there, more than

one thread can hop in there.

Leo Dion (host): Okay.

Matt Massicote (guest): And so, and
that's the danger, is that it's kind

of similar to queues, where like, if
you need to do some work in a queue

and it's all serial work, you're safe,
you can totally isolate everything.

But if you want to hop out to some
other queue, do some long work, and

then get back into that queue, somebody
else can get in, another thread can

get into that queue at the same time.

It's a very similar kind of problem.

Leo Dion (host): Okay.

Matt Massicote (guest): And so,
there's this wonderful package called

semaphore that is a concurrency
compatible lock and it lets you

solve that specific problem.

If you look at the actual
implementation required to make

something simple like a cash to
value in an actor, it is bananas.

It is bananas how complicated it is
and it's because of this re entrancy.

Leo Dion (host): okay.

Matt Massicote (guest): And a
simple, a simple concurrency

compatible lock, you cannot use
the regular locks and semaphores.

But a concurrency compatible
lock makes it so much easier.

It's worth it.

Leo Dion (host): Okay.

Yeah, I've actually had to use a
dispatch semaphore for an async

call because there is no, like,
that's the closest thing to a

semaphore I had in i i i in Swift.

So, yeah, I feel like that's
definitely something missing.

Matt Massicote (guest): it is.

And so there's, there's one built, but
the dispatch semaphore has a problem

because of the concurrency runtime
requires that all actors be able to

make forward progress and a regular
semaphore breaks that requirement.

So you rest, you risk hangs
using a regular kind of lock.

Leo Dion (host): Was there anything
you missed from dispatch queues?

Matt Massicote (guest): So, so we're
talking about locks here and all this

why actors don't solve that problem.

So, but, so there's also,
there's no mechanism.

Actors, even if reentrancy is a thing,
actor reentrancy is a thing that they

address, which is being seriously
talked about for Swift 6, because a

lot of people are having this problem.

Even if that gets addressed, it still
does not help you with ordering.

Or

Leo Dion (host): Right, right,

Matt Massicote (guest): stateful system,
there's no way to control how things go.

So there, you need a queue.

A queue is a thing that
you're going to need.

Leo Dion (host): Yeah.

So like one of the things I think
people, I actually, like I said,

I think it's a feature, it's a bug
because one of the things that I had

to learn is that when I first started
async await was that I assumed in

a function, when you run a bunch of
async stuff in a function, it was

going to do it in in, not in an order.

So I'm in like the opposite boat.

And then I learned, Oh, if you want
things to not run in an order, then

you have to do like the async let.

In order to do things in a non order.

This is not what you're running into.

You're

Matt Massicote (guest): No, I,
yes, that is, that is confusing.

You're right.

Leo Dion (host): Because I was
like, I don't, like, these things

don't depend on each other.

Compiler, please just
run it in whatever.

Like, run them all together.

I don't care.

And then I was like, Oh, you have to do
this async lat, which is totally not...

Like, that's a little bit weird to

Matt Massicote (guest):
I agree with you.

It

Leo Dion (host): Because it's like, the
whole point of async away to me is like,

I don't, these things don't, unless they
depend on each other, and I figured the

compiler can figure that out, I don't
need to tell it, like, it should, it

should just run it in whatever order,
I don't care, like, so that was one of

the things I first had to, had to learn
is like, oh yeah, use this async let to

let it know that I don't care the order.

Matt Massicote (guest): Yeah.

Well, you can do that for things
that are, have no dependency.

So if you're doing like ABC
and they don't matter, then

you can do that kind of thing.

But if you have like, you're going to
do a, and it's an async call, and then

you need to use the result of that
in B now the ordering is required.

So within a particular context, within
a particular async context, it's

all going to run things in order.

Leo Dion (host): right, by default,

Matt Massicote (guest): these contexts.

Leo Dion (host): around, which is
your issue, where you have Function

over here and function over there.

Yeah, yeah, yeah.

Matt Massicote (guest): And I think
that's, so that's one of the reasons

why I think there was this deep
misunderstanding even internally at

Apple is the, when, when async await
was originally introduced, there's

this automatic translation that
you can use between a a completion

Leo Dion (host): handle her.

Yeah.

Refactor and Xcode.

Yeah.

Matt Massicote (guest): it'll
just like magically make it work.

And I think that is, that was
done because I don't think there

was a deep appreciation for how
dangerous that kind of thing can be.

Because that kind of change can be so,
if you're thinking, oh, I'm just going

to change it into an async an async
await, and I'm going to wrap it in a

task, that it has different semantics.

And so you're changing, when
you make these refactors, you're

actually changing the semantics
of how the code works as well.

Leo Dion (host): Yeah, yeah, totally.

Matt Massicote (guest): And I'm not
sure everybody understood that one.

Leo Dion (host): it seems like you're
looking at some of the SWIFT proposals.

What do you see out there as something
you're looking forward to that kind

of remedies some of these issues?

Matt Massicote (guest): Oh,
well, there's a, there are many

changes that are out there.

So one really difficult one that I
think is also pretty hard to understand,

even before concurrency was out there,
is needing to do stuff in a D init.

So in your dinit method, if you
have a main actor thing, you're

thinking, okay, my dinit is going
to run in the main actor too.

But that is actually not the case.

And I think that is really
surprising to people.

Even from objective C, you might think
like, how could it be my view is being

deallocated, not on the main thread?

That's, doesn't seem right.

Leo Dion (host): Even if you, like,
even if you mark your whole type

as, or class as main actor, it's
still not gonna run, didn't it?

Okay.

Matt Massicote (guest): yeah, yeah.

And this is, this can be a
really big problem for certain

Leo Dion (host): I would

Matt Massicote (guest): Yeah.

Yeah.

And I don't know that they have fully
sorted out what they're going to do

about it, but it is an understood
problem and it cause UI kit.

I don't even think this is well
known, but UI kit and UI view in

particular, it goes through these
Herculean efforts to try to make sure

your D in it, or your, your dialect
actually does run on the main thread.

Leo Dion (host): Okay.

Matt Massicote (guest): But it requires
an enormous amount of work at the

app library level to make it happen.

Leo Dion (host): Okay.

Matt Massicote (guest): And so I think
that they're trying to solve this

problem and I think that'd be wonderful.

But I don't know yet if there's
currently any solution out there.

Leo Dion (host): Okay.

Matt Massicote (guest): So that's one,
that's one that's being talked about.

Well, there's this whole property
wrapper changing actorness.

That's a, that's a really confusing one.

I'm really happy to see that
one has been accepted and

it's gonna, gonna happen.

Leo Dion (host): Okay.

Have you looked at any
of the observation stuff?

Does any of that?

Okay.

Matt Massicote (guest): to,
but I haven't seen it yet.

Leo Dion (host): Okay.

Okay.

Matt Massicote (guest): I mean,
there's also things that are

tangentially related to async await.

Like.

I have had a really hard
time using async sequences.

Leo Dion (host): Okay.

Matt Massicote (guest): of, one of
the reasons why is async sequence does

not have a primary, the protocol does
not have a primary associated type.

So you can't use any async

Leo Dion (host): Yeah, nah,

Matt Massicote (guest): You
can't use any async sequence.

Leo Dion (host): right.

Matt Massicote (guest): And so
that's usually not a big deal

unless it's at an API boundary.

Leo Dion (host): Okay.

Matt Massicote (guest): And then
it's an enormous deal because what

type are you supposed to return?

Leo Dion (host): Okay.

Yeah.

Yeah, that's weird.

Matt Massicote (guest): it is weird.

Yeah.

Leo Dion (host): because they slapped on
primary associated types so many places.

It's so weird that

Matt Massicote (guest): you know,
it was, it was, it was intentional.

And the reason why was they
were thinking about how they

were going to expose the error
property of async sequence as well.

And I think that's what
caused the hook, the hangup.

But I would love to see it.

I would love to see it because that's,
that's been a problem for sure.

Leo Dion (host): and I'll put a link
to my talk at Swift heroes somewhere

in here So people can check that
out if they want to know why primary

associated types are so important

was there anything you looked
at at DubDub DC this year?

You said, you said a few
things, like what specifically?

And anything that
related to Chime I guess?

Matt Massicote (guest): Well,
you know, I was hopeful for

some more extension kit changes.

There's a few little things
that have been problematic,

but there was nothing there.

No, there was nothing really.

I mean, I'm always interested in
what goes on with the text system

because there was this big migration
from TextKit 1 to TextKit 2.

And I would say that
that has gone largely.

Terribly text kit two is, is
getting better, but it is so

it was, it was launched in
an absolutely unusable state.

I'm amazed that it, that it chipped.

That was with, I think
that was Mac iOS 11.

So that was two years ago.

Last year it got a lot better.

But still has some really major bugs
that I don't know how to work around.

I haven't tried hard, but
I know that it's a problem.

So I was hoping for a little bit of talk
about like what's new in the tech system

and maybe some changes that would help.

I didn't see anything there.

The things I did see, I think
the macro stuff is fascinating.

Leo Dion (host): Mm hmm.

Yeah, I agree.

Matt Massicote (guest): a lot
of people have started to feel a

little bit like Swift is getting to
be too complicated of a language.

And it's complicated.

But yeah, but I, I think that it's,
I think it's a very interesting

direction to go in anyways.

These are the fundamental problems,
they have to be solved somewhere.

And so I like the idea of people
thinking deeply and trying to come up

with a, a solution in the language.

Leo Dion (host): I have an
idea for a talk here about

how complicated Swift is.

I, it's, it's been floating in my
head, but yeah, I have an idea for

a talk I want to put together on
why people should try not being too

intimidated by it and, you know.

Anyway.

You'll see that in the future.

Future, in the future, soon.

Cool.

Is there anything else you
wanted to cover about Async Way

about Chime before we close out?

Matt Massicote (guest): Well, you
know, so, last year was all about me

adopting extension kit and building
this API that was never going to work.

And then this year, kind of in
the background, I've been slowly

chipping away at fixing it.

And I can say that it's, it's
been incredibly difficult.

And I think the reason why
it's difficult, one is that

actorness is very viral.

So if you find there's this
one little thing you need to

change to be main actor, it's
a big, it can be a big problem.

So that's one thing another thing
is, you know, you got to be careful

with protocols because protocols
and actors and even main actor

isolated objects don't always mix.

And I think that we've been very, as
like a swift community have been very

quick to use protocols everywhere.

And that can be problematic
when when adopting concurrency.

So that was a one that
was tricky for me.

But I have, I'm pretty close actually.

So I, I'm almost finished.

Updating an enormous amount of packages
and a big API surface to actually

be something that works correctly
and concurrent with concurrency.

And is I think also what I want.

So I'm very happy with that
progress, but it's been very tough.

Leo Dion (host): awesome.

Well, I am excited even though I
won't be in Toronto, I'm excited

that you'll be presenting on
this topic and telling people all

the lessons that you've learned.

I think it's gonna be
awesome and fascinating.

Matt, thank you so much for
coming back on the show.

I really appreciate it.

Matt Massicote (guest): Absolutely.

Thank you for having me.

Leo Dion (host): Where can
people find you and Chime online?

Matt Massicote (guest):
Well, Chime is at ChimeHQ.

com.

And I've just finished removing
all of the bird site references,

so you can find me on Mastodon.

You can find me on Mastodon.

social slash at Maddie M.

Leo Dion (host): It's
on a bird site today.

Today, as of the recording, it's,
it's an X site, so you actually have,

I'll have to, yeah, I'll have to fix,
I'll have to fix this in editing,

make sure that people know it's the
X site, not the bird site today.

People can find me on the X site at
LeoGDeon but I'm also on Macedon at

LeoGDeon at My company is bright digit.

Please take some time.

If you're watching this on
YouTube to like, and subscribe.

And if you're listening to this on a
podcast player, please give me a review.

If there's anything you want to talk
about or anything you want to hear

about, let me know, DM me, email me.

Send me an X, I guess.

I don't know, whatever it is.

But and also buy a ticket to Swift
Toronto if you haven't already,

hopefully this episode will be
out in time for you to do that.

Thank you everybody.

And I look forward to
talking to you again.

Bye everyone.