Apple announces full Swift rewrite of the Foundation framework (2022)
infoq.com
infoq.com
It's probably another big step towards "Swift everywhere," without worrying about bridging to C.
I've been doing little but Swift since 2014, and really like the language. I'm still "on the fence" about SwiftUI, but that's mostly because of the level of support from Apple, and the [im]maturity of the system. This will help with that.
I‘m a little sad though that they didn’t start this endeavor years ago, because IMO Rust has already built so much momentum that it will win (for the popular, medium to long term definition of „winning“).
I find using apps written, using hybrid systems, or PWAs, to be quite painful (on Apple devices -and that includes that awful JS TVOS system), so I am a big proponent of real native apps.
For example, a UI framework may implement good transition animations. That’s pretty typical. Write an extension to UINavigationController, or UIViewController (if you use UIKit) that implements these transitions, package it as a standalone project, and integrate it, or simply have project-specific baseline framework extensions.
That’s what I do. I have a ton of these packages[0].
It’s a fair bit of work, to do it yourself, but there are package[1] and extension[2] indexes. Caveat emptor.
[0] https://riftvalleysoftware.com/work/open-source-projects/
This is already pretty much true today, aside from the few, mostly down-in-the-weeds holes in Foundation on Linux that will be solved once this rewrite is complete.
Cross-platform command-line tools, web backends, and things like AWS Lambdas are all possible and pretty easy to do today.
Writing Rust applications is also very ergonomic. The Rust web server frameworks are approaching the ergonomics of Typescript web server frameworks.
The only Rudy lacking ergonomics is writing net new frameworks or missing framework pieces, or when std is not available.
95%+ of all new Rust code will fall into the bucket of “ergonomic to write and read”.
The pain of adding third party C++ dependencies is undeniable, especially in a cross-platform manner. I've had the displeasure of maintaining three different C++ build systems in 3 different companies, and they were all a nightmare.
Contrast that with cargo that just... works.
This is also, if not more, true for Swift as well. I've been working with both Swift and Rust (in addition to C++) for some time now and I find real-world, advanced Rust SIGNIFICANTLY easier to read and comprehend than real-world, advanced Swift. This is, IMHO, due to the fact that where Rust chooses to be syntactically simple, explicit and consistent, Swift chooses to be syntactically complex, idiom-based and feature-bloated. Sure, Swift code can look very modern and attractive at times, but usually when it comes to superficial code samples in Apple promotional videos. Otherwise, if you, say, look at a large codebase written by someone else, Swift reads just as badly as C++ complexity-wise.
None of them are ergonomic for non-trivial applications!
The goal is to appropriately abstract away the super minority of code that deals with the non-trivial parts into a nice ergonomic interface.
Rust is frankly better than most in the list above at allowing the writer to create an ergonomic interface. Yes it’ll take the writer 3x as long in the short term to create the ergonomic interface but:
1. Relative to everything else creating/maintaining these types of internal abstractions is a super minority of time spent reading and writing code.
2. Unlike other languages, you’ll end up with fewer iterations of the interface because it’ll push the author to really understand the complete interface, rather than shipping a buggy interface that needs iteration. Also refactoring is Rust is simpler than any other of the listed languages (because it self documents more assumptions).
3. The ergonomic interface likely has already been published as a crate. I.e. don’t need to write it at all. These internal abstractions are more likely to be written in their first pass as general purpose than in other languages because of the collaborative design working with the rustc compiler.
I agree! You’re currently dealing with writing non-ergonomic Rust.
I’d argue your domain is missing a fundamental reusable library/framework or the framework is currently missing a piece. Once someone publishes the needed library (hopefully it’ll be you) then everyone consuming it can just Lego block multiple crates together. Lego blocking crates together (barring heavy macro crates) is very ergonomic.
95% of all new code written is Lego blocking other crates. 5% of new code written is to build new or improve/patch crates.
I don't think that's true at all, at least it wasn't for me. Async in Rust has always been hard for me, it seems that using it requires knowing about how exactly it works and how your runtime of choice works. This is a lot, and requires a lot of time.
The documentation in Rust is above average, however the Rust ecosystem tends to be very unstable. Libraries often pull lots of depencies, many of which aren't even in 1.0, some that have switched to a new version but still have docs made for the old. The guideline from semantic versioning is to release 1.0 as soon as people start depending on it, since the idea is to version the public API. This is not always respected. And goes hand in hand with libraries that are 4 years old and on version 12 or something.
I remember actix-web before the 4.0 being particularly hard to get into.
We saw the other day where C and C++ just let you write what seems reasonable but then they do something insane, D says no, that's a syntax error, but Rust's diagnostic gives a name to what you intended, says you can't do that, and suggests how to write it instead.
if (a < b < c)
C and C++ think that's doing a comparison, coercing the boolean result to whatever type to compare it with the remaining variable, and then acting on the new boolean result. D says that's a syntax error because there should be a closing parenthesis after the variable "b". Rust says "comparison operators cannot be chained" and suggests a < b && b < cEdited to add:
Swift says: adjacent operators are in non-associative precedence group 'ComparisonPrecedence' -- which is definitely better than D, but it doesn't offer the helpful suggestion.
the section on the future hopes for Swift similarly; it seems both Rust and Swift contend to replace C++ in many use cases
This "lower-level Swift" felt like a similar problem to what Carbon or Herb Sutter's Cpp2 have. They've got something that's unsafe, and they want to somehow build a safe abstraction, but that's a foundation layer, and you've already built a tower of stuff above that, so you need to build it underneath all the stuff you have, which will be way harder than what Rust did where they begin at the bottom.
Is it impossible? No. But it might well be too expensive to be pulled off in practice, especially given that you need the result to pay back your expense over and above what exists today e.g. Rust.
MS is interesting - they tried to write memory safe C and invested heavily, but admitted defeat eventually - and started using Rust. And I think that’s what will happen at most companies eventually. Rust has a lot going for it (faster than C sometimes, excellent WASM support etc). Swift might have been another contender, but Apple kept things too close to their chest for too long IMO.
As another poster wrote, Swift certainly won’t die at Apple (and their ecosystem), and Google will certainly keep Go alive. But I think Rust will eventually be used at many/most other companies for anything security or performance critical. Maybe it will replace C as the de facto low level language.
Note that android-ndk in that comment means the original Makefile based build tooling, which CMake builds still lack some corner cases in functionality, hence why I listed both.
Do I get an Android test phone to try my software out? Is there like free phone support so I can chat to some expert in my language about Android problems? You make it sounds like a pretty big deal, but my small experience† of writing Android software a decade ago was that it just wasn't that hard.
† I wrote an implementation of the now obscure mOTP (similar to TOTP) for in-house usage. For obvious reasons I named This One Time app "Band Camp" which was already a pretty old reference at the time but once I thought of it I couldn't help myself.
The languages with tier 1 support on Android SDK tooling for app development, properly configured out of the box after a SDK full install.
https://developer.android.com/guide/components/fundamentals
Which by the way, also includes a phone emulator to try out your stuff, including simulation of hardware events.
No need to get a phone.
I just tried this and... no C++. You can add the NDK and start building stuff with C++, but that's also exactly how the Rust offering works. If the result was actually a properly configured out of the box C++ development environment that would be pretty nice besides the Android stuff, but it isn't, the actual result out of the box is you get to pick Java or Kotlin.
You can do C++ native development for Android, but only via basically the same route as Rust, there's just not the huge gap you implied.
Has out of the box support on Android Studio for:
- mixed language debbugging
- project templates wizard
- code completion and linting
- JNI bindings generation
- two way editing between native JNI wrappers and Java/Kotlin native method declaration
- packaging of Android libraries for native code
And for game developers, if they so which, plugins for Visual Studio with similar capabilities.
In both cases, official support from Android team if there are issues with the above tooling.
Apparently you haven't tried enough, if you think bare bones NDK integration with cargo is enough for Android shops.
Maybe Rust will get on https://developer.android.com some day, but it isn't there today, even despite the fact that it is being used for Android internals, there is zero documentation on how to write Android drivers in Rust.
https://source.android.com/docs/core/architecture
So lets not pretend it is the same effort using Rust on Android, as it is for the official SDK languages.
Can’t speak for Rust (but I hear that it is now quite mature -it predates Swift), but I’ve been programming Swift, since the day it was announced. In that time, the language, itself, has matured; possibly to the point that it’s starting to look a bit “Swiss army knife”-like.
I’m not exactly your typical jargonaut. I’ve been writing software since 1983. Been through a lot of changes, paradigms, and just plain old bullshit, in that time. I don’t really go for “shiny,” just because all the kids are into it, these days.
I can understand the appeal of abandoning Objective-C.
It's not just memory safety. Go gets motivated by highly concurrent systems with large numbers of programmers and prioritized simplicity and developer experience. Rust was aiming at very high performance at the extended of complexity and compile times, and Swift wanted to build UI hierarchies.
Had Java been like Modula-3 or Eiffel since version 1.0, Go might never have happened at all.
Thankfully they are on the right path to fix those issues.
Additionally, AOT is still experimental, and doesn't support ASP.Net Core yet.
J++ extended Java in having a Windows specific framework JFC, Java Foundation Classes, what later became Windows Forms.
Support for events and J/Direct, which is basically how P/Invoke came to be on C#.
.NET has always supported a basic kind of AOT via NGEN, which only supports dynamic linking, AOT has to be done at install time, requires strong named Assemblies and it is tailored for fast startup leaving the rest of the work to the JIT.
If it wasn't for the lawsuit, C# would never happened, in fact the research being done with COM vNext used J++.
Sorry for the nit but Mozilla didn’t give us Rust. They sponsored some of its development but that was only 3ish years after Rust started.
Sitting hairs really.
(I’m now curious if the unowned keyword would have similar performance characteristics)
I should also perhaps mention that Swift is my favorite language to develop in. I’m not trying to be antagonistic, just realistic about its prospects against Rust.
Compiler optimizations are exactly that, optimizations that any automatic memory mangement implementation usually takes advantage of.
This is false. People believe it on faith without measuring:
https://mikeash.com/pyblog/friday-qa-2016-04-15-performance-...
> A normal Objective-C message send is a bit slower, as we'd expect. Still, the speed of objc_msgSend continues to astound me. Considering that it performs a full hash table lookup followed by an indirect jump to the result, the fact that it runs in 2.6 nanoseconds is amazing. That's about 9 CPU cycles. In the 10.5 days it was a dozen or more, so we've seen a nice improvement. To turn this number upside down, if you did nothing but Objective-C message sends, you could do about 400 million of them per second on this computer.
So it's 9 cycles vs what, one?
I'm not sure what you're asking? What are you trying to compare?
Also, for the most part, it’s vastly superior to Obj C. The sad thing is that when writing Obj C I often find myself not writing the clean, well structured solution that’s in my head out of sheer resistance to the verbosity that it would take. I always just keep thinking how simple it would be in Swift and how much longer and more keystrokes / files it takes in Objective C.
https://mjtsai.com/blog/2022/12/12/the-swifty-future-of-foun...
>it sounds like the plan is to rewrite it in Swift and extend Swift to allow Objective-C to call the Swift implementation of the old API
Looking forward to it.
And then they still take a cut of your revenue.
Objective-C had a good run. I haven’t used Objective-C in over 10 years but I have used Swift about 10% of the time in the last four years. Swift is a nicely designed language and I could see it supporting Apple’s business for many years.
Will Swift ever be a primary language on Linux? I would say yes, except now that Rust is used the advantages of also mixing in Swift are diminished.
https://developer.apple.com/library/archive/documentation/Le...
https://en.wikibooks.org/wiki/WebObjects/Overview/Objective-...
Those were the days! Actually kind of amazing that the Foundation framework is the result of steady evolution of an ObjC framework written by NeXT... over 30 years ago? All those `NS` prefixes that are still hanging on are for `NextStep`.
If this really replaces the ObjC implementation... would that be the final sunset of the codebase that has been there (at least ship of theseus style) from NeXTStep days? I wonder if there's continuous version control history of Foundation source from the start, and how many, if any, lines of code remain from the initial implementation.
A lot of the web services that Apple provides still use that implementation of Foundation :)
EOF 1.0 was the first product released by NeXT using the Foundation Kit
One way or the other, their development was closely connected/overlapping.
https://en.wikipedia.org/wiki/Distributed_Objects_Everywhere
Their collaboration is also one of the reasons why Java is basically Objective-C semantics with C++ like syntax.
https://cs.gmu.edu/~sean/stuff/java-objc.html
Interfaces (protocols), dynamic class loading (plugins), RMI (distributed objects), jars (bundles), dynamic dispatch by default, object root class,...
It’s like Java, just sweeter ;)
So they jumped into the Java hype, created their own JVM implementation, with Swing extensions for the OS X UI, and Cocoa Bridge was born for Objective-C interop, with bindings for all key Apple techonologies like Quicktime and such.
When it became clear that Objective-C wasn't going to be an adoption problem, instead of using a 3rd party owned language, they dropped support for Java and eventually gave their implementation to OpenJDK.
> With a native Swift implementation of Foundation, the framework no longer pays conversion costs between C and Swift, resulting in faster performance.
and this:
> A reimplementation of Calendar in Swift is 1.5x to 18x as fast as the C one (calling from Swift in various synthetic benchmarks like creation, date calculation).
First, that range of 1.5x-18x is kind of huge. Why?
Second, why would the intro with C be such a big performance penalty even assuming it's just 1.5x? I know there must be an overhead, but why so large?
Also, why single out the Calendar? Is it somehow representative?
This is somewhat analogous to the same arguments that can be had about JIT compiled languages having the the opportunity to exceed performance of AoT compiled ones because of inlining opportunities- except in this case I don’t know if the call has any chance of being actually inlined so much as at least bypassing the message passing machinery overhead.
- better understanding of the problem that needed solving, which leads to: - structuring the application so it is better suited for what it actually has to do - better choice of data structures and the algorithms that operate on them - concurrency was more easily usable, hence the code would often run on more cores
In a couple of cases I discovered that Java was inherently faster because it coincided with "what the GC likes". In some cases Java turned out to be more CPU intensive, but that this was mitigated by being able to use more cores, so the user experience was better. (There were also setbacks: anything that looks like an LRU cache for instance is not friends with the GC, and you'd have to do silly tricks with NIO ByteBuffers plus serialization and whatnot).
A lot of Apple software is buggy, badly designed junk. It used to be worse, but you can still see that a lot of their software does beginner mistakes such as blocking calls in the main event loop, resulting in "spinning ball of fail" type blockages.
Some of their system software tends to misbehave as well, consuming lots of CPU and making the fans spin up if left unaddressed. It seems to be some kind of rule that for each release there is at least one daemon that shits the bed.
Does this change imply better (eventual) support on non-Darwin systems? Or maybe I've misread it and the change is unrelated.
It is not, but it's like 95% of the way there in my experience - most things that are missing are relatively recent additions that have some complex OS interactions, like filesystem I/O with language-level concurrency features.
> Does this change imply better (eventual) support on non-Darwin systems?
Yes. The non-Darwin Foundation version is already rewrite that takes a lot of effort to keep in lock-step with the closed-source Objective-C version, so unifying the implementations in Swift will both reduce the amount of maintenance effort and promote non-Darwin platorms to more of a "first-party" status.
> Also, is Foundation the same thing as what one might normally term a standard library?
It's more of a standard library++, including some things that other languages include in their standard libraries (Date/Time models) but also other things that are common to put in third-party libraries (networking, etc.). You do not need to use Foundation for basic things like arrays or concurrency that are built into the normal standard library.
Do you mean like io_uring? That wouldn't be too surprising. Even Go doesn't have that in the standard library yet.
> so unifying the implementations in Swift will both reduce the amount of maintenance effort and promote non-Darwin platorms to more of a "first-party" status.
That's what I was hoping for. Thanks!
I'd call that a language feature. Or maybe with Swift there is a blurry line between the two?
https://github.com/apple/swift/blob/main/stdlib/public/core/...
Swift is fantastic, and by far my favorite language to write client code in. (Compared to Rust, TypeScript/JS, ObjC, C++, C#, & Java.)
When you're own government's security services are spying on you, they own you.
These security exploits also get used by local police who wouldn't have access to the top government access used for terrorists.
There already was an open-source project to rewrite ALL of foundation, but it had stalled on the shores of having to re-implement everything:
https://github.com/apple/swift-corelibs-foundation
The news is actually that Apple is now instead trying to define the bits/parts to support via Swift on all platforms (the original API's will always be supported on Darwin).The announcement:
https://www.swift.org/blog/future-of-foundation/
The discussion, with hairy details about which bits, esp. for async: https://forums.swift.org/t/what-s-next-for-foundation/61939/103
The plan is to divide up Foundation into more- and less-essential parts, to get more-essential parts locked down so people can rely on them.What's Foundation? Swift's most-core library is the stdlib, tightly coupled to the compiler/language version, providing things like arrays, dictionary, etc., and available wherever Swift is. Beyond that, Foundation is the library with core API's for common features, e.g., for dates and concurrency. Stdlib is fully cross-platform and Swift-specific, but Foundation is a beast with API's dating to NExT with support for 20 years of API's.
Microsoft famously arrived at porridge for an operating system by maintaining backwards compatibility. Apple has cracked open Swift by developing in the open, but it's still Apple-funded and Apple-driven. Library and some integration support for other platforms has always had to come from community (notably compnerd's heroic effort to make-things-work on windows, and a revolving cast wanting Linux support for their server API's).
But there's no good reason to impose the whole Foundation history on other platforms. And there may be a movement inside Apple to migrate internal code to newer async API's, designed after the recent Apple-silicon generation.
For developers with server experience and some free time in a tech lull, it could be a good opportunity to help rebuild a new, er, foundation for computing on all devices, that's native but type- and memory-safe. The community is large and mature, but there is plenty of room for others.
If Apple wants people to use Swift like a first-class runtime, they should stop treating third-parties like second-class citizens. They have $200 billion dollars in cold, hard cash - surely some of it could go towards the selfless development of a universal future computing platform, right?
By this a mean common distros like Debian Stable must have a package for core libs, going to https://www.swift.org/download/ doesn't cut it.
There’s a few interesting old videos on YouTube where Steve Jobs is answering developer questions in the audience.
Apple focused on the product and the customer, while Microsoft focused on “developers developers developers.
We don’t need another Microsoft.
We need them both to be different.
I often wonder what things would be like if Apple had improved upon Objective-C by fixing up the underyling C language. Yeah it'd no longer be a superset of C, but so what? Neither is Swift. Swift is great but I wish it was closer to Objective-C in spirit by deliberately being a more lightweight language. It's language spec is gargantuan - they've pretty much succeeded in making it a language as complex as C++.
Merely adding generics and better typing akin to TypeScript's, to Objective-C would've worked wonders and made the transition less abrupt.
https://medium.com/ios-os-x-development/generics-in-objectiv...
I still rely on some stuff like GCD that isn't very swift like, there still isn't anything as fine grained in Swift, but I'm liking combine in some cases.
For professional *OS development Swift probably makes sense. But if I occasionally need to write some code, Objective C for me is preferred. May be Swift is stabilized enough already...
The biggest source-breaking change on the near-term horizon (which is still in progress) is compile-time enforcement of concurrency safety.
me dont understand what make it faster now. i once wrote some jni code to call c++ library from java. does mean there some similar code to do cross language call? they get rid of it and so things now faster?
offtopic but debugging crashes in c++ over jni call was super hard. logs not work and me not figure out how to fix. wonder if they had similar “troubles” and this make everything easier :)
always feel skeptical when seeing large code base have “rewrite”. try many time in me career thinking there good reasons but super hard and not best value in end
And will it be binary-compatible with existing apps, or will Apple just ship a separate compatibility version of Foundation for use by legacy apps?
They're already binary compatible, in the sense that you can call compiled Obj-C classes from Swift apps (of course), and also - with some restrictions - call compiled Swift code from Obj-C.
In fact, you can "swizzle" methods in Swift just like in ObjC, on classes derived from NSObject:
https://medium.com/@valsamiselmaliotis/method-swizzling-in-s...
This means code that tried to swizzle foundation types, assuming foundation is developped in objc, will not work anymore once foundation is using a pure swift implementation.
The alternative would be for Apple to break compatibility with old Obj-C apps, instead shipping a compatibility version of Foundation.framework which old apps would continue to link against. But it sounds like they're not going that route.
But in fact, the most valuable part of the code in any nontrivial system is the “unsafe” yet safe ones. You write memory safe code by understanding how computers memory works, sometimes you can use certain patterns to make that process easier, but not always. This is regardless what language you use: you programming in Rust, still the most valuable part is where one can get the “unsafe” part right.
A good C programmer will always a better Rust programmer when he wants to. That’s it.
Really looking forward to OOP being phased out.
All the higher level macOS APIs are still object oriented, and I don't see that changing TBH. And macOS application source code is essentially just minimal glue code to tie those system APIs together, in the end, the programming language used for this glue code doesn't matter all that much, since the code is completely dominated by API calls.
At any rate, I apologise for using such an ill-defined term as "OOP" in the first place. This terminology is so overladed and washed out at this point that it might sense to retire it altogether.
The only built in types in Objective-C are the C types, like int, char and so on. The "Foundation" is a set of classes that implement many useful types that all inherit from a superclass called NSObject. The "NS" prefix refers to Next Step, the name of the company that Steve Jobs started and where Foundation was first created.
One of the advantages of this scheme is that it is possible to have heterogeneous collections (like an array of objects, where the objects do not all have to be of the same type/class).
Underneath the NS foundation (whose headers are all in Objective-C) is something called Core Foundation, which implements the same classes, but in pure C. To do this well requires huge programming discipline, especially around memory management, and much of that pain is taken away by using the NS classes.
Swift has already started replacing some of the foundation classes, NSString and NSDictionary, for example, giving them the names String and Dictionary without the cumbersome name-space two letter prefix.
I suspect that some of this rewrite may still "bridge" to the CF classes, but in other cases, it would be much better to simply write the class in its entirety in Swift.
I hope that helps.
Windows has WinAPI which is basically the same thing.
[1] https://github.com/apple/swift/tree/main/SwiftCompilerSource...
And if so, what benefit would it provide?
But pieces absolutely could be. The benefit would be compile-time checking for memory safety issues (reducing crashes) and language-level concurrency (fewer race conditions and a much easier path to parallelize single-threaded code for performance).
It sounds to me like Apple would like Swift, perhaps with some extra tooling, to be able to handle the Mach kernel. I don’t know if they’ll go that far though.
That possibility is still a ways down the road of course but Foundation getting a cross platform rewrite is a nice step in that direction.
relevant listen is about 2min long
On the other hand, your comment said ”working on _a_ Swift compiler for Windows”. To me, that sounded like a new compiler, not adding missing features to the existing one. Which of the two is it?
Swift structs are just like C structs (from a memory perspective). The copy-on-write thing is implemented manually by storing a private refcounted object in your struct. See the implementation of Array for example: https://github.com/apple/swift/blob/main/stdlib/public/core/...
There’s no magical copy-on-write mechanism at the language level.
I know, right? Some people are pretty insecure…
Swift has an emphasis on value types, which often are stored on the stack, but only up to a certain size. Copy-on-write makes this feasible - often, those value types are passed by reference until a write actually occurs, but that’s opaque to the dev. Value types can have pointers to reference-counted types - if a value type is passed/copied, any pointer it owns is retained (weirdly enough, they claim that value types have no „lifetime“, but at some point those refs have to be released - we just have to trust the compiler in this).
I've not paid attention to Kotlin in a while, but it seems like there's more progress at supporting Kotlin across more platforms (Kotlin native, web?, etc). I'm curious if people feel that the language features and design are at about parity, or if one is significantly stronger/weaker.
BTW, JetBrains recently sunsetted AppCode, so they are bleeding their Swift talent now. I suspect that doesn’t bode so well for Kotlin‘s Swift interop.
Nowadays it runs everywhere and supports a variety of deployment targets (relying on local runtime, packaging it together into a single somewhat compact binary, natively compiling the code (NativeAOT, it's good but has some limitations) or mixing and matching all of the above).
It is also one of the best high-level languages to write performance-oriented code with, especially so with .NET 7 which allows writing cross-platform SIMD code in a similar fashion to Rust's 'portable-simd' crate.
And while it's tangential, Xaml drives me absolutely bonkers. It's like the worst parts of iOS Storyboards and Android Framework XML layouts except there's no escape hatch for those looking to build a UI in pure code (Android Framework is a bit of an offender here too, but Jetpack Compose looks to remedy that).
This is interesting because all these magical functions (zip, map, Rx etc) have roots in LINQ which sprung from .Net world. I find it hard to believe that the battle tested CLR and C# doesn't have the equivalent functions.
No they don't. They're essentially unchanged from ML back in the 1970s. The part that was new in C# was the SQL-like syntax on top of them, and most subsequent languages haven't considered that worth adopting.
UI frameworks on the other hand…I feel your pain.
That said I've only used Kotlin in the context of Android development. It might be nicer elsewhere.
Kotlin has it's roots in JVM and the early language design choices clearly reflect that. Kotlin/Native will find it very hard to break free of it's JVM counterpart because it can't diverge too much from it to maintain compatibility.
Swift and Kotlin are in many ways similar, but I find Swift to be a bit nicer in almost every respect. Swift has more powerful generics, tuples, structs, powerful enums that are value types, `if let`/`guard let` statements that I'll take over `?.let {}` any day, etc. Kotlin is somewhat more expression oriented, which is nice; Swift is moving in that direction too, but slowly.
A native Kotlin (I have no idea how mature it is) might be a decent alternative to high-level Rust, but I'll take Swift if it's available. It's both more pleasant to work in and I assume more performant with better access to stack allocated value types.
It feels like Rust is two languages in one: a high performance zero cost abstraction language that tracks pointer ownership, and a package rich and hyper explicit application language build atop all the guts. That's why I say high-level application use cases, because most high-level applications are not concerned with raw performance but rather with functionality and user experience. The parts that are concerned with throughput can be implemented using tooling where those knobs are available. I have enjoyed writing a cli and api server and various libraries in Rust. But every so often I am left wondering when Swift might be able to replace it for my higher level concerns. Alternatively, it would be neat to see some effort put behind a "convenient rust" type of compile mode for modules where you could compile with things like implied clones, unified owned vs reference types, auto-arc/box, etc.
Personally I'd love to see a forked flavor of TypeScript with static compilation and multithreading (which implies a lot more immutability, etc). Maybe I should give Swift a try…
Just about GC language has similar tradeoffs. The question here would be why Swift over Go/C#/Java/Python/Typescript?
1. Much more expressive and featureful than Go
2. More concise and modern than C# (debatable maybe?)
3. Less JVM than Kotlin (the apples-to-apples; Java is a much worse language)
4. Way, way faster and more typesafe than Python
5. Better support for parallel execution (and probably fine-tuning other performance knobs) than TypeScript
2. I think the C# team has done very well modernizing. The runtime is a bit of a bother though.
3. There's Kotlin/Native and Kotlin/JS.
4. Python has dev speed and ML benefits.
5. If you're going this way, performance probably isn't your main goal?
All-in-all, Swift is interesting, but (IMHO) lackluster crossplatform support and toolchain is a problem.
If you can come up with a precise transform from "convenient/sloppy rust" to the underlying language, it can already be implemented via proc macros and the #[attributes] syntax. This is how async programming was prototyped in Rust before it became part of the language proper.
Though I'm not sure it's fair to describe Rc, Arc, Cow etc. as "library bloat". It certainly adds some boilerplate, but it's designed to stay manageable.
(Arguably, good coding practice should also informally document why the Rc, etc. is needed and can't be refactored away, i.e. what parts of the program are controlling the lifetime of each Rc'd object.)
Maybe it was a mistake to conflate lifetimes and generics. It wouldn't be so bad to deal with references in Rust if you didn't have to include lifetime parameters when building APIs. It seems silly that (in my experience) people gravitate toward structs with owned fields just to avoid specifying the lifetime of a borrowed field.
Swift is slower than C++, yes, but not because of its memory management scheme.
I wouldn’t call RAII “reference counting”. I mean, I guess, but it’s the programmer or the compiler doing it. I’m talking about runtime reference counting.
Go ditched OO for similar reasons.
Haskell, Erlang, and more get along fine without OO.
(OO crested with Smalltalk, Java, Ruby, Python, and JS (more prototypal though). Let's not talk about C++98)
Sure, or really OCaml or any other language with ML-family features (other replies have already mentioned Kotlin or C#). But the fact that it took Rust to get adoption and not OCaml suggests that it's not language functionality that drives adoption; Rust has something that those languages don't. (My theory is that it succeeds by being the first decent language that can match C's performance-on-silly-microbenchmark numbers)
I Google for stuff and probably 3/4s of the result are out of date and won't work in any reasonably modern version of Swift. I find Apple's Developer documentation sub-par, to say the least. So, how do you navigate it all?
It's quite a shock coming from stuff like Go, C#, and Rust.
It'd be pretty cool if there were a good version of the Swift Cookbook Ala the classic Perl Cookbook.
Network comms are generally done using URLSession: https://developer.apple.com/documentation/foundation/urlsess...
Reading files is most often done using the String and Data types:
- https://developer.apple.com/documentation/foundation/nsdata/...
- https://developer.apple.com/documentation/swift/string/init(...:)
I've found Apple's documentation for Foundation to be quite exemplary.
https://developer.apple.com/documentation/foundation/file_sy...
Those are generally enough to get you to the point where you can make sense of Apple’s documentation.
The only reason I learned Powershell is because I have to admin for Windows. At least Powershell is interesting for its pipeline and object handling. I get not one spark of joy from Swift, and the comments I see are "at least we're not writing C anymore". Stockholm syndrome.
Sorry this is so negative, but I can't get excited about $NewLanguage unless I know it offers real benefit. I have drunk the Rust koolaid, and for very good reasons. What am I missing in Swift?
A very Apple thing to be honest, so just like most of the Apple products it’s very good in few thing and good enough in others and probably nothing is completely new.
The overall experience is pleasant. Apple is building just as pleasant tooling around it, Swift Playgrounds is amazing for example. Newbies can learn coding by doing some exercises disguised as games but that’s not what’s amazing, what’s amazing is that you can make full apps with all the libraries and Swift packages and SwiftUI. Apple did good job hiding the boilerplate away, did good job removing the decision making about the project file structure and created an intuitive interface where you can just code without worrying about anything else.
In 2020s, Swift is probably the only language with tooling that lets you just code your ideas and deploy without dealing with anything else. Like creating a Word document and writing your thoughts down straightforward.
I don’t know if submitting from Swift Playgrounds to the AppStore has been released but the beta I was trying last month had this functionality. From idea to market, start to finish integration.
#!/usr/bin/env swift
print("hello, world!")No reason why Java and C++ couldn't do something similar though.
Ideally it gives you some of the convenience and accessibility of a language like Python, combined with runtime efficiency of a language like Objective-C.
print("hello, world") is a cute example since it's a valid program in both Python and Swift.
(Though I still haven't forgiven Python for removing the print statement, which dates back to BASIC antiquity.)
It actually feels quite a lot like Rust to write it. They're obviously designed for two different use-cases – Apple platform development versus safe systems programming, but they share a lot of similarities in other ways.
Swift might not change the industry, but it makes life easier for anyone who wants to develop on an Apple platform but finds Objective-C unwieldy. Also it provides a path for Apple to migrate its platforms to memory-safe languages, which can reduce bugs and security vulnerabilities.
Apple's thing is innovation - taking technology that exists but is clunky and making it accessible.
Swift is intended to be a more accessible alternative to Objective-C. It is memory safe (reference counted like Objective-C's ARC but built into the language) and type-safe, and has modern features such as named parameters, generics, duck typing, closures, multiple values, inline arrays and dictionaries, etc.. It's intended for writing user apps, but is also suitable for writing system frameworks. It also has some (possibly overly) clever syntactic sugar that has enabled SwiftUI's pseudo-declarative API.
Regarding memory safety we have: Swift (mostly reference counting), Rust (mostly compile-time checks), Java (mostly garbage collection), and C++ (smart pointers or manual/unsafe.)
https://learn.microsoft.com/en-us/powershell/scripting/insta...
OTOH PowerShell actually works largely the same across all supported platforms, so it's equally useful on all of them in absolute terms. Now, outside of Windows, we've had decent shells for much longer, so its relative utility is indeed lower on those platforms (although not non-zero, if you find the notion of an object-oriented shell with a rich standard library useful). One particular use case where it comes in handy is when you have to script some automation for both Windows and Linux; e.g. cross-platform builds or CI. So mostly shared code, but in a few places you might need to do "if LINUX then ...".
…also, the multithreading design is better and more performant.
…also, it has a stable ABI that supports shared libraries, which no other compiled language except C ever manages to get right.
But hey, we're stuck with it now so no use complaining.
Memory management is easier than it is in Rust. It has generics which makes it more flexible than Go [was until its generics were recently introduced]. Kotlin native wasn’t announced until three years after Swift.
I don’t think it’s as simple or one-sided as you’re making it out to be.
guard let foo = bar else { ... }
to be any better than this:
if bar().is_none() { ... }
For the record, I find the guard keyword totally unnecessary and I still have NFI what's wrong with this in Swift:
if bar == nil { ... }
I also totally disagree about memory management being "easier" (at least with C-interop), because I think Swift's handling of UnsafePointer/UnsafeRawPointer/UnsafeBufferPointer/mutable variants/withMemoryRebound/etc isn't particularly easy to follow at all.
To be clear though: I don't think Swift is a bad language. It's perfectly adequate. But it's the fact that Apple decided to force Yet Another Programming Language down our throats that, in my opinion, offers no real advantage over many of the other choices available at the time.
"We're Apple and you will only use a language that we control" was, IMO, the driving force behind Swift, not the inherent superiority of the language itself.
> Swift's handling of UnsafePointer/UnsafeRawPointer/UnsafeBufferPointer/mutable variants/withMemoryRebound/etc isn't particularly easy to follow at all.
And that’s why we have inout instead? Unsafe* is useful if you need to bit pack frozen structs into a ring buffer and increment the r/w offsets by the stride, maybe? I think inout can handle that as well.
(Todd said this would never happen)
Also, this is great news, and it will be interesting to see what kind of real-world changes in performance this has.
I don't have a link, so feel free to treat as hearsay, but FYI.
Swift is generally slower than Objective-C, often significantly so. There are cases where it is faster, but those are rare.
Yes, I have measured.
One example is JSON and Swift codable, which is comically slow, see:
Somewhat Less Lethargic JSON Support for iOS/macOS, Part 1: The Status Quo
https://blog.metaobject.com/2020/04/somewhat-less-lethargic-...
Punch line: Swift codable does around 10MB/s, despite all the supposed performance goodies and compiler support everyone always talks about and nobody appears to ever measure. A pure Objective-C implementation does 284MB/s.
I also did a more general survey for my book[1]. While that's been a while, I haven't seen any indication that things have fundamentally changed, and lots of indications that they haven't.
In particular Swift is more memory efficient than ObjC because there's less boxing overhead to small values. That should matter more than the overhead from more overflow checking.
This is another commonly held belief that doesn't hold up to actual measurements.
For an example, see part 2: https://blog.metaobject.com/2020/04/somewhat-less-lethargic-...
All the pure Swift implementations are even slower than the bridged ones, and the bridged ones are slower than the most comically inefficient Objective-C one (using KVC, for example), which is slower than the reasonable Objective-C ones.
> In particular Swift is more memory efficient than ObjC ...
It's not.
> ... because there's less boxing overhead to small values
You would think, yes. I actually did think that as well. Because it really sounds plausible. So imagine my surprise when I measured some common cases for my book (Chapter 9) and it turned that even in the cases where I just knew™ that Swift would be faster, because of this very reason, it just wasn't.
> That should matter more than the overhead from more overflow checking.
Computers don't care what you think "should" be the case, and they cannot be argued into better performance due to plausible arguments and strongly held beliefs.
You need to measure what actually is the case.
You generally make the choice between writing something in pure C, which gives you plenty of performance but little safety, or using Objective C classes and methods, which gives you plenty of safety but you're paying the price for dynamic dispatch (objc_msgSend) and pointer indirections all the time.
Swift makes it easier to eliminate things like dynamic dispatch while still keeping the safety. So it should be normal and expected that a rewrite from Objective C to Swift would result in a speedup (and increase in code size).
In my experience, old-school ObjC iOS and Mac apps generally tended to be quite snappy.
On the other hand, the new Swift hotness of Messages and Settings on macOS are noticably slower than what they're replacing.
Of course I haven't done a comprehensive inventory, but I certainly don't have the general impression of things getting faster with Swift. (Are there examples of this?)
My guess is any theoretical gains are generally swamped by the language culture of complex abstractions.
Somebody rewrote a library in Swift -> the library is faster.
There's a lot to talk about and unpack here. My experience is that people develop a different mindset when they do library development, because any code that they write will be code that they're forced to support for decades to come. You put bad code in an app and you can simply rip it out with the next revision, no questions asked. So you are much more likely to end up with questionable code in an app than in a library.
I'm also old enough to remember not only the same complaints when people were rewriting apps into Objective C (lots of early Mac OS X apps were Carbon, including Finder), but when the same complaints were made about rewrites from assembler into C. Every decade your computer has a hundred times more computing power and your code takes 10x as much footprint, so you come out ahead, on average. It's just that any given year you might come out behind.
For more details, see iOS and macOS Performance Tuning: Cocoa, Cocoa Touch, Objective-C, and Swift, Addison-Wesley
https://www.amazon.com/iOS-macOS-Performance-Tuning-Objectiv...
If you don't want to read a book, here is an example as a series of blog posts: https://blog.metaobject.com/2020/04/somewhat-less-lethargic-...
Ten years ago a “Tanya” told me she would never use an ebook to read literature. I’m pretty sure if I went to her house today I’d find 2. In fact I may be the only person I know who doesn’t own one (not wanting one and being fundamentally against them are two different things).
That’s the most memorable but I’ve had these sorts of “over my dead body” conversations on a hundred topics over the years.
They're not really comparable formats. PDFs are documents rendered onto virtual paper: there is only so much a mobile device can do there, as a PDF is likely rendered as an 8½ by 11 or A4, which isn't going to be great on a tiny mobile screen. Bad tradeoffs between tiny text or pan-and-scan.
eBooks, OTOH, are reflowable: ePub is "just" a ZIP of HTML¹. But the viewer can lay them out appropriately, so they can be formatted to fit your device, whether that's a tablet, a phone, or something else.
IMO if you want to read something on a device, ePub > PDF for those reasons. PDF is good for print, & ensuring that what comes out of the printer has a shot at resembling the screen. (Though there are a good number of print settings to mess that up, too.) And, as a passably portable document format, if you're just doing short term viewing or something.
¹Plus a lot of other metadata that I'm eliding; it's a fair bit more complicated, of course.
GP probably meant “ereader”.
There seems to be a trend here.
Microsoft is dropping C#? Source for that?
However Mark Russinovich, CTO of Azure did say that it's time to drop C and C++
https://twitter.com/markrussinovich/status/15719951172335042...
Syntax isn't the reason why C and C++ are falling out of favor.
Everything else is just as good of an idea as the next. C family is the most successful language paradigm in the history of software. Abandoning those constructs would be suicide. Nothing would get done.
"C-like", by contrast, is a language whose semantics follow closely to C, and in particular, the C-with-extensions languages like C++ or Objective-C are usually going to fall into this category.
If you don't believe me, quit all your non-Apple apps, and open up Console.app and hit Start streaming, and limit only to the "Errors and Faults" and watch the computer scream in logs until you're convinced. This is what modern Apple software quality looks like. I really don't want them touching anything near the core OS. Especially because when Apple software doesn't work, either you'll get no feedback, or it will say something comically vague like, that it "can't be completed."
I'd LOVE to be proven wrong here because otherwise I'll have to finally catch up on my Windows knowledge and get used to not having a GUI metakey separate from Ctrl!
I’m sure Jaguar had zero errors and had all the code audited by Steve Jobs himself to make sure it had top quality.
And for real what indicator is there that Apple has low-talent employees? Do they not pay well with good benefits? Where exactly do you expect all the good systems programmers are working?
I don’t think a company with bad low level engineers would be bragging about wake from sleep times in their marketing materials.
I don’t know of any other desktop OSes that replaced their entire file system with a routine OTA update transparent to the user.
I can think of other big recent changes like how people criticized the new System Settings panel a bunch, but at least Apple didn’t take 10 years of iterative updates to not even finish the transition. Please, someone tell me why Windows 11 still has the old Control Panel when Apple replaced their entire settings panel in a single update.
As stupid as it is, in my mind the simple fact that iOS just added a “copy and delete” button to the screenshot capture UI tells me that there are still plenty of power user geeks at Apple. We shouldn’t be surprised that they happen to care about different things than what we cared about in the 90s.
We can nitpick the bugs all day but I can’t think of another desktop OS that executes on its goals as consistently as macOS, commercial or not.
Luckily I had a backup, but it was about a month old.
Cocoa and Carbon and OS9 emulation... it was terribly unstable. But sure the current rock-solid-haven't-restarted-my-computer-in-6 months version is terribly unstable! Want proof? Explicitly turn on logging and watch the logs... log. xD
But I do stand by the statement that overall, the experience is a lot better on MacOS
For example after all these years and lots of requests for such a feature it's still not possible to get notified about new reviews for your apps, but it's possible to get notified when a user edits a review after you've replied to it.
> (roughly) Japan is a country for the Japanese. While they may welcome you and invite you to experience their country and culture, the country is very much setup to serve the Japanese populace.
Apple feels similarly. They build what they need and enough to capture the revenue they want, but I don’t perceive them to really cater to external needs beyond what will monetize.
So then why does all of Apple's operating systems and apps receive updates at all.
Your argument is completely illogical.
I don't think Apple can do a full rewrite of Foundation, unless its opt-in only for Swift apps that have been ported to the new Swift-only codebase. If they are trying to opt in non-Swift apps, well, I'm glad I don't use OSX nor have to support it.
The article linked has few details on how they plan to do this, or how they plan on limiting the blast range.
It seem that microsoft care way more about developers at the moment than Apple does. So much good stuff, open source, Linux subsystem, vscode, copilot, documentation, plugins, etc. Things works and are cheap and plentiful.
Beside the sleek and high quality hardware, nothing is missing.
Everything you listed is on both platforms?
What are you actually comparing?
I don't think it would be worth my time to even buy a other macOS device to port my framework.
I don't think they will get any benefit from this.
I don't see any good reason for them to deprecate the ObjC-Swift bridge, but I guess they could decide it's too much work to maintain.
But at least they relied on the LLVM toolchain and the NeXTStep heritage, it was possible to use clang and many C APIs and a few wrappers around the horrible Obj-C APIs.
With Swift I don't think this will be as practical, if even possible.
They are so rich and powerful that they don't care. And most devs on their platforms are happy to drink the kool-aid.
This will take time, because they have relatively strong foundations and deep pockets, but they are going to slowly sink their ship, what they are building these days is technically unsound and pretty soon their engineering culture will have completely changed.
The Swift/C++ bridging stuff is pretty exciting though. A lot of engineering is being thrown into this.
These sorts of statements in the industry always make me ask, "So did you guys make something terribly slow first, and then bring performance back close to where it originally was?"
I'm not sure if the current Calendar app was ported to Swift, was originally Objective-C based, and such efforts to move Foundation to Swift will just... make Calendar fast again?
Also, Calendar doesn't seem to be particularly slow in the first place. But I love performance engineering, and quality of life is big, so... hey cool.
They’re talking about the Calendar class in Foundation.
In this case, the answer is basically, "yes". Objective-C is a neat language and really powerful in terms of flexibility and extensibility. But it gets that by essentially dynamically typed. It's Smalltalk duct taped onto C.
Dynamically typed languages are much slower unless you do lots of very powerful JIT magic, and even then they still tend to be quite a bit slower than most statically typed compiled languages.
Building Swift on top of an Objective-C core library makes a lot of sense in terms of getting Swift adoption when Swift was new. But in terms of performance, it's sort of like building a concrete bunker on top of a straw hut. You really want the bottom of your stack to be the faster, statically typed language. Then you can layer dynamic scripting languages on top for the users who want it.
I’m sure it is, but this is not solving the right problem at all. Calendar is all UI. It needs to be lovingly gone over, not this.
> NSCalendar objects encapsulate information about systems of reckoning time in which the beginning, length, and divisions of a year are defined.
> The Swift overlay to the Foundation framework provides the Calendar structure, which bridges to the NSCalendar class.
https://developer.apple.com/documentation/foundation/nscalen...
The reimplementation itself is not 1.5x to 18x as fast as the C one. It is calling from Swift that is faster.
Yes, they correct in the parenthesis, but that's not how parenthetical expressions work:
A parenthetical expression is extra information added to a sentence or question that clarifies, explains, or adds information without changing the basic meaning. Think of it as an aside providing readers with helpful information that they don’t absolutely have to have, but that is helpful to them.
https://grammar.yourdictionary.com/style-and-usage/parenthet...
So basically, they are fixing the problem they've been having with bridging performance, which of course is due purely to them mis-designing Swift in such a way that it doesn't bridge well with all the existing code they have.
The reimplementation itself is 1.5x to 18x. They are using the parenthetical in precisely the way the style and usage guide suggests, adding the additional information that the new implementation is called from Swift.