Archive for November 25, 2024

Monday, November 25, 2024

Swift Vision: Improving the Approachability of Data-Race Safety

Holly Borla (via Mastodon, forum):

This document lays out several potential paths for improving the usability of Swift 6, especially in simple situations where users aren’t intending to use concurrency at all.

[…]

A key tenet of our thinking in this vision is that we want to drastically reduce the number of explicit concurrency annotations necessary in projects that aren’t trying to leverage parallelism for performance. This is important for many kinds of programming, such as UI programming and scripts, where concurrency is often localized and large swathes of the code are generally expected to be constrained to the main actor. At the same time, we want to maintain a smooth path for experienced programmers to opt in to concurrency and maintain the safety of complete data-race checking.

[…]

We believe that the right solution to these problems is to allow code to opt in to being “single-threaded” by default, on a module-by-module basis. This would change the default isolation rule for unannotated code in the module: rather than being non-isolated, and therefore having to deal with the presumption of concurrency, the code would instead be implicitly isolated to @MainActor. Code imported from other modules would be unaffected by the current module’s choice of default.

[…]

Adding a per-module setting to specify the default isolation would introduce a new permanent language dialect. […] On balance, we feel that the costs of this particular dialect are modest and manageable.

[…]

The most important of these for our model of single-threaded code is to be able to express global-actor-isolated conformances. When a type is isolated to a global actor, its methods will be isolated by default. Normally, these methods would not be legal implementations of nonisolated protocol requirements. When Swift recognizes this, it can simply treat the conformance as isolated to that global actor. This is a kind of isolated conformance, which will be a new concept in the language.

Marcin Krzyzanowski:

what I’ve been complaining about since when first Actors introduced to Swift is that it forces “async-first” instead of “sync-first” programming. I’m super happy the Swift Language Steering Group has finally noticed it.

Christian Tietze:

So much effort poured into this, and then the DX problem can be summarized like “you can’t easily write single-threaded code now anymore” 🤯

Max Seelemann:

That said, for such a broad vision, I’m missing coverage of the present issues with isolation behavior mismatches to Objective-C code and Objective-C system libraries.

To this date, much of Apple’s new platform development is still done in ObjC, and many – if not most – Apple platform developers can’t evade UIKit or AppKit in their day-to-day work. Yet this language does not know anything about strict concurrency and allows comfortably programming in very non-compatible ways. What I dearly miss are tools to bridge this gap, to make using those APIs from Swift 6 as comfortable as it is from Swift 5 or ObjC.

[…]

Most importantly, to me, we need more robust and flexible ways to declare dynamic MainActor isolation. Basically MainActor.assumeIsolated but for entire classes and without all the sendability-dance for passing things in and out of that closure. (#isolation being non-nil when called from the ObjC main thread would also be nice.)

[…]

I struggle to write this more precisely in abstract terms, so I’d like to give an example from my recent work with TextKit2 – a fairly new system iOS/macOS API, that’s thought and written entirely in ObjC.

Victor_Martins:

My understanding is that the document says that one of the reasons that analyzing the program as a whole is bad is because “it would make the first adoption of concurrency extremely painful”. Then, it goes on to say that a better approach is to make the single-threaded assumption in smaller parts of the program. Finally, the document proposes that these smaller parts are the modules.

Choosing the modules as the smaller parts have caught my attention because over the last 3 years I’ve interacted with a couple dozens of beginner Swift programmers and the vast majority of the apps I’ve seen them develop do not have the code they’ve written broken down in smaller modules. The apps are mostly composed by 1 module + dependencies.

Is breaking out of the single-threaded default on these projects with one big module possibly going to be quite painful?

Previously:

Update (2024-11-26): Rob Jonson:

I think you’re absolutely right to focus on these - but I would argue for a radically different approach.

[…]

Flip the default. The default should be that guaranteed data race safety is turned off. […] Moving to an opt-in model will change the dynamic. At the moment, it feels like we’re on a forced march to the promised land of Swift 6 safety. If safety is opt in, then developers will choose to use it as it becomes more ergonomic. If the feature has to be worth the pain to convince people to opt in, - the dynamic around design will focus more on real usage.

[…]

Analyse code was a great tool as we moved towards arc (and even later). Run the tool, examine warnings about memory safety, fix if needed. […] Concurrency could do the same thing. Analyse could warn me that returning an NSImage is potentially unsafe if the sender keeps and mutates the original - but I can choose to ignore that because I know I’m not doing so.

I’m not sure I agree with this, but it’s interesting to consider.

Tim:

I remember the exact same arguments about optionals when Swift was first released. “I know what I’m doing”. “The compiler is trying to baby me” etc etc. Understanding optionals is definitely far easier than concurrency, but it’s the same thing of a language feature tackling common programming errors and I think we can all agree that it’s been a great feature once understood.

I’ve always been in favor of optionals, but I think the other way of looking at this is that people quickly saw that optionals provided real benefits in reliability and code clarity at very little cost (cognitive or visual). Beyond the async/await sugar, Swift Concurrency’s costs seem much higher and its benefits less clear.

Apple Tends to Do Right by Apps It Acquires

John Gruber (Mastodon) has gone through the list of Apple acquisitions:

The bottom line is that what we, as users, hope for after a big company acquires a beloved app is for an outcome where the users of that app remain happy. That might mean just keeping the app going, like with Logic. Or it might mean scrapping the standalone app, but bringing the core features of the app into the OS itself, like with Dark Sky. Sometimes it’s a mix, though, like with Shazam.

[…]

But an examination of Apple’s acquisition history doesn’t give me any reason for alarm. Apple really does tend to do right by cool app acquisitions.

[…]

Pixelmator in particular is simply too good to scrap, and Apple hasn’t made its own bitmap image editing application since, I think, MacPaint. Something like Pixelmator really would slot right in next to Final Cut Pro and Logic Pro as an Apple “pro tool”. Whether they’ll keep the name, I don’t know, but I think the app will be released under Apple branding as a Photoshop competitor, for Mac and iPad.

[…]

I’m less sure if Apple has the appetite to keep Photomator going, to compete directly against Lightroom — a market Apple simply walked away from when they discontinued Aperture 10 years ago. But perhaps they now regret walking away from Aperture. I’m just not sure how close Photomator is to being a credible alternative to Lightroom.

[…]

I can see how the best of Photomator could make its way into Photos. That’s not true for Pixelmator. The acquisition just doesn’t make sense to me unless Apple wants to make Pixelmator an Apple-branded pro tool.

My immediate reaction is that acquisitions are almost always bad for fans of the original app, however, I think Gruber is right that Apple’s track record is better than average. On the other hand, looking at the list, most of the businesses that Apple acquired weren’t apps. It’s not a big sample size.

Two apps that were dear to me are Claris Emailer and ClarisWorks. Claris did a great version 2 of Emailer, after acquiring it from Fog City Software, and then killed it. Presumably, this was because Apple had acquired Mail.app in the NeXT acquisition. Unfortunately, it didn’t really try to integrate the things people liked about Emailer into Mail, and it lost some of the key developers to Microsoft.

Similarly, I guess ClarisWorks was killed in favor of iWork (itself based on an acquisition). The AppleWorks Carbon version that shipped after Apple resorbed Claris was not great. iWork is OK but never appealed to me in the way that ClarisWorks did, and it was missing the painting, drawing, and database modules.

More recently, the Dark Sky, Buddybuild, and TestFlight acquisitions were good in that they expanded Apple’s services, but I don’t think they were necessarily wins for fans of the originals.

Previously:

The End of Delicious Library

Wil Shipley:

Amazon has shut off the feed that allowed Delicious Library to look up items, unfortunately limiting the app to what users already have (or enter manually).

I wasn’t contacted about this.

I’ve pulled it from the Mac App Store and shut down the website so nobody accidentally buys a non-functional app.

Previously:

Black Friday 2024

My apps (DropDMG, EagleFiler, SpamSieve) are on sale for Black Friday, and here are some other good deals that I found:

Apps:

Accessories:

Books:

Photos and Video:

Stores:

Lists of Deals:

Previously: