My memory might fail me, but I thought Swift 4 was supposed to be "the last major breakage"? Swift has a new major revision every year.
Compare this to Go (no major revisions after 6 years, probably a backwards-compatible major revision in 2-3 years) and Rust (no major revisions after 3 years, but with a mechanism called "editions"). To say nothing about Java or C#.
Neither of those languages launched out of the gate with a stable ABI. Prior to Rust 1.0 it was much the same, with regular breaking changes. C++ famously took many years to have a stable ABI.
Swift 5 represents a stable ABI. That means from this point forward all binaries built with Swift 5 or later will run against a newer Swift stdlib.
The ABI is entirely separate from source compatibility. Swift is already source compatible and the bar for a source-breaking change is extremely high.
> C++ famously took many years to have a stable ABI.
I'm pretty sure C++ doesn't prescribe any particular ABI for implementations to adhere to. There was even a paper in 2014 about defining a portable ABI, and I don't believe it was adopted [0].
In particular, MSVC uses a different ABI than the *nixes, and MSVC's ABI isn't guaranteed to be stable across major compiler releases. In addition, libstdc++ 5.1 had a significant break for C++11 std::string and std::list [1].
The Swift 5 release process document specifically implies that some Swift 4 code will not compile on Swift 5. This discussion is about source compatibility, not binary compatibility, which neither Rust nor Go offer AFAIK.
The number 5 _also_ implies significant breaking changes. Otherwise, why wouldn't it be Swift 4.3?
Removing Swift 3 compatibility mode (which was part of Swift 4) is itself a major source-compatibility breaking change, even if nothing else.
So far there are only a handful of small breaking changes between -swift-version 4 and -swift-version 5 on the master branch. The only ones I can think of are a type safety hole getting plugged and some warnings for corner cases around access control that got promoted to errors.
There are basically two parts to ABI stability. Memory layout, and calling convention. C++ defines the memory layout ABI exactly - two c++ compilers will (theoretically) produce identical struct layouts irrespective of inheritance, virtual vs non virtual classes, etc
C++ implementations generally use a calling convention that is stable ABI on each platform, but different platforms may have a different ABI. In the past the MSVC ABI was different from most posix platforms, I’m not sure if that carries through to win64.
The easiest way to explain why C++ the language doesn’t prescribe the calling convention ABI is that you may want to compile code on different cpu architectures. There’s no way you could (sensibly) have the same calling convention :)
There's way more to a stable ABI than that. All of the standard library for example. Try making a binary library that uses `std::string`. It can't really be done - you have to take `const char*` and convert to `std::string` internally.
I think you're confusing maintaining ABI stability with at an API level, vs. ABI compatibility at the language level.
ABI stability at a language level is for code (replace syntax with your language of choice):
class Foo {
virtual void bar();
int _i;
float _f;
bool b;
int bitfield : 5;
}
Should be stable across multiple compilers and versions. This is what swift currently does not have.
This is vs. source defined ABI, e.g.
class Foo {
virtual void bar();
virtual void wibble();
int i;
float f;
}
vs.
class Foo {
virtual void wibble();
virtual void bar();
float f;
int i;
}
In this example Foo is API stable, and the language ABI means either definition is ABI stable, but as a publicly exposed API it is not ABI stable. C++ defines vtable layout in terms of order of definition (so changing the order of virtual methods is not stable). And you have the source compatible reordering of i and f, which is just as ABI breaking in C++ as it is in a C struct.
The library is compiled into SomeLibrary.dll,dylib,so or what have you.
Your program uses this:
void my_cool_function(Foo* foo) {
foo->bar();
}
Later on the library makes a change, and adds a new virtual method wibble(). The API is stable -- they haven't removed Foo::bar, and they haven't changed its parameters or return type. But this API change can break the library ABI if it declared the new virtual method in the wrong part of the class, because vtable ordering is defined as being order of declaration.
So there are two aspects of ABI compatibility. First, does a given API result in the same ABI irrespective of what compiler version it uses. The second is, given that your language is ABI stable, are your changes to the API also ABI stable. C++ is notoriously bad at this, because of foot guns like vtable ordering, changes to binary layout of superclasses, etc.
Swift is at least in existing versions even less stable, where you're not necessarily guaranteed that a single API will get the same ABI depending on what things it is compiled with, and certainly not through even minor compiler version changes - let alone actual language version changes.
The compiler has a -swift-version flag which gates the source-incompatible changes. There were a number of changes between -swift-version 3 and -swift-version 4, including the two you highlighted. The delta between -swift-version 4 and 4.2 released this year was much smaller.
The real issue I encounter isn't Swift itself, it's the constant Swift-specific SDK changes... When the `NSNotification.Name` Swift APIs change every year, it means migration is still painful.
It's not the Great Renaming, and it might not be fair to the Swift project itself, but unless I can compile a project using the 10.13 and 10.14 SDKs without source changes (which you can in Objective-C), the impression is that Swift doesn't have source compatibility.
The Swift compiler does a lot of automatic "rewrites" of (Objective) C headers to be more Swifty, so it does have some measure of control. That said, the largest changes are guided by annotations associated with the headers.
I'm not disputing that. What I am saying is that, until the Swift representations of the Apple platform SDKs are stable between releases (like it is in Objective-C), then the majority of Swift codebases will not be source compatible the way Objective-C codebases are.
Unfortunately, this isn't how Apple works. Both teams are more or less separate in this case. Sure, the Swift team can certainly send information over to the AppKit team, but they don't have the ability to make any decisions on naming conventions.
That is compiler compatibility. I am talking about language-level compatibility.
Yes, you can continue compiling v3 code with a v4 compiler with a flag, but if you compile your v3 code without a flag, your code may fail to compile. So while there may not be a compiler breakage, there is a language breakage between v3 and v4, and apparently there will be another one between v4 and v5.
That is right, but as I wrote in another reply here the changes from 4 to 5 are miniscule, mostly just fixing corner cases where the old behavior was not correct.
> When the Swift 4.2 compiler is working with Swift 3 code, it identifies its language version as 3.4. As a result, you can use conditional compilation blocks like #if swift(>=3.4) to write code that’s compatible with multiple versions of the Swift compiler.
If long-term stability is your goal, Swift is definitely not yet for you. Perhaps after v5, things will settle down. That seems to be what they're aiming for, but I would wait and see.
> but I thought Swift 4 was supposed to be "the last major breakage"?
It wasn't even major. I updated several projects from Swift 3 to 4 without issue. The largest project was close to 200k loc and it only took me 20 minutes to get everything up to date.
Just make sure your dependencies aren't in Swift because then you're relying on 3rd parties to update their code. I'll be avoiding all Swift libraries except for PromiseKit (it's so nice!).
What I really miss in Swift are user definable attributes. Also I would like to have the Objective-C attribute that requires you to always call super. I don't think that Swift even honors that attribute if it is defined in Objective-C.
I consider it weird that the "where" keyword can't be applied in more places, only in case and for ... in I believe it works. Seems like some weird remnant of "what cool feature of C# could we borrow?" that never really got a full rollout.
Also I would like to have a "not" keyword instead of using the easily overlooked !. Such a nice feature of F# (and Visual Basic?).
Good to see count(where:) coming to the language, I often missed it. And probably is faster than filter since it doesn't create an array of results first.
Apart from that Swift 5 doesn't seem to be super different from 4. But that's what I expected already.
Where do you miss user-definable attributes from? I'm not aware of any analogous ObjC feature.
The `where` keyword is also used when defining generic functions/types. As the expression level, it used to be used in `if` too, but that syntax was changed such that it no longer uses `where` (but still retains the same power). Where else were you expecting it to be used?
You can do a non-allocating `count(where:)` today with `lazy.filter(where: …).count`.
Question for the HN language designers: do you think it's possible to provide ABI stability when the language still doesn't provide the full promised features for concurrency ? (ex: async / await, agent based concurrency, and all the features talked about in chris lattner's concurrency manifesto)
An ABI can't really be "additive". If you add stuff to an ABI, it's a new ABI. Unless you tweak the definition of ABI to your liking (like introducing new concepts as "module stability").
Let's say you have an iOS application written in Swift 5 and you are using AlamoFire. The original promise of an ABI (like the C ABI, the ObjC ABI, COM, JVM, etc) is that AlamoFire could choose to switch to Swift 6 because of the great new async/await features, and you could still use that binary in your Swift 5 application. Because, you know, there is a stable ABI ;-)
If you enhance the ABI, that won't be usually possible. E.g. the Swift 5 program won't understand the "new mangling and calling convention" mentioned in the link. Presumably it could be bridged somehow, or maybe not in a useful way ...
> An ABI can't really be "additive". If you add stuff to an ABI, it's a new ABI.
Not really. You can add new concepts to an ABI without breaking existing code.
Suppose version N+1 of some compiler adds a new language feature, like async/await or whatever. It might involve a new calling convention and symbol mangling for async functions. However non-async functions would not be affected.
Of course if the library author removes old entry points they will break old client apps, but that's not a property of the compiler.
"The primary goal of Swift 5.0 is for the language to achieve ABI stability."
"Apple’s Chris Lattner, original creator of the Swift language, has recently announced on the Swift Evolution mailing list that ABI stability, one of the goals originally planned for Swift 3, will be postponed."
Well, one "surprise" is that a new thing called "module stability" was invented. The Swift ABI isn't going to be the ABI-thing you are used to from C (or COM) or JVM or, well ABIs ;-)
And sure, they'll give you an ABI. But whether that is going to be a _stable_ ABI is to be seen. I have some doubts given the complexity of the language, but we'll see how it turns out.
Swift suffered the fate, of being a language developed by an academic to say and developed within a large corporation. It ended up being a complex language with useful features. Newbie hackers can't at all master protocols, generics and all the cruft. If it was simple as GO, and from day one designed to run on servers instead of iOS, Swift would've had incredible adoption given features as optionals, type safety and python/c like syntax & first class functions.
Why not use Flutter? Even React Native is cross platform. Why are we still using a programming language for a phone app that means we have to write the darn thing twice? Even a RN webview pointing at an IP with code written in whatever-lang is seemingly a better choice.
Have you ever developped anything serious with swift ? Honestly, this is by far the best language i've developped in (including go, java, c#).
Note that i'm talking about the language here. The libs are of various quality. But powerful enums & switch + null safety + generics while retaining the ability to be learned easily by any "regular" developer makes it a category of its own.
My secret hope is that someone somewhere is working on a flutter equivalent coded in swift.
Have you looked at Crystal? It has a lot of the same strengths you note that swift has, but with stronger Linux support and a more rubylike expressibilty and stdlib.
Swift has a nice mix of features that allows you to write pretty close to functional while also allowing you to write code that compiles to the same code as equivalent C (albeit a bit more verbose).
I don't think there are any languages out there outside of Rust (which has it's own niche since Swift is ARC and Rust is more or less manual) that does the same.
I honestly never understood why F# has never managed to get more popular. Ocaml style type system with .Net lib support would have make it an absolute killer language if it were really advocated by MS, but they probably thought the language was too different from C style to be really mainstream...
I haven't done .Net for a couple years but Microsoft never really supported F#. It wasn't a full-fledged citizen in their web frameworks; you could include compiled modules that you made with F# but couldn't use it the way you use VB or C#. And you'd think a functional language would be great for data transformations in SSIS, but same deal there, just VB or C#.
Microsoft always positioned it as "use F# for the hard stuff and C# for the rest." The trouble is that C# isn't that bad for the hard stuff, and if you're spending most of your time with C#, then for you it's probably better than F#.
Microsoft's management cannot make their mind what it is good for, mainly because FP is not really something that 99% of typical enterprise developers care about.
When they made it officially part of .NET, it was the black swan of .NET languages with tooling only for libraries and command line applications.
Afterwards they attempted to position it as a language for ASP.NET MVC applications.
Then they largely left it for the community as F# was one of their very first FOSS projects.
Meanwhile the new MDIL compiler came out for Windows 8.x, followed by .NET Native, none of them support MSIL features required by F#.
Likewise .NET Core only accounted for C# and VB.NET, and they are still reimplementing type providers and the REPL for it.
Finally after all these years F# still lacks tooling for Forms, WPF and EF.
Meanwhile C# keeps getting some F# features.
Currently F# is being positioned as a language for data science with its type providers and Azure Netbooks.
Except kotlin doesn't have anything close to swift regarding enums + switch (like : enum with associated values of various arity, and a switch that makes sure you're handling all the cases), nor regarding null safety.
And, it still has java underneath, which means everytime you're using a java lib, you have absolutely no idea what the null safety is going to be underneath (which is also the case with swift and objc libs, but which diminishes the attractivness of using the java libs ecosystem)
EDIT: also, value-based programming is highly encouraged by the full support for structs, either mutable or immutable. That's also a huge plus for safety against race conditions.
Kotlin has sealed classes (enums), when expressions (switch checking) and absolutely does have null safety. It also reinforces null safety when using Java libraries if they have nullability annotations.
Swift is not seriously useful for server-side applications at this point. None of the web frameworks have even remotely great performance, and Swift is compatible with almost nothing on Linux, since Apple has put minimal effort into anything but macOS and iOS... so anything you do would be much more painful than using Go, Rust, or even C# (.net core) on Linux.
So, maybe you're just talking about desktop macOS in addition to phone apps?
It literally only compares itself to slow, interpreted languages and other, even slower Swift frameworks, with the singular exception of Go, where they're using Gin, which is a rather slow Go framework. Gin is at literally 10% of the performance of the fastest Go framework, as shown here: https://www.techempower.com/benchmarks/#section=data-r16&hw=...
So, when you cherry pick benchmarks, it can _look_ kind of fast... but then the unbiased TechEmpower benchmarks show Vapor operating at 20% of the speed of Gin. Which is 2% of the speed of the fastest Go or Rust web framework.
"50x faster to pick a different language" != "even remotely great performance."
I’m not sure this is a great benchmark (detailed in a comment above), but I think it’s undair to criticize a web framework for comparing itself to Django, node/express, Elixir/Phoenix. While dynamic languages, there’s billions of $ running on those frameworks and to present yourself as a fair alternative to those is good enough.
(I have no personal interest in Swift on the server, I use Go/echo)
i think the techempowered benchmarks [https://www.techempower.com/benchmarks/] don't show a pretty picture for swift-based web framework. But hopefully swift nio will change all that..
> We were pleasently surprised to see Vapor coming in first as being asynchronous does not really help with plaintext benchmarks. Plaintext benchmarks are really only good at testing how fast a web framework is capable of parsing and serializing HTTP headers.
I did not look if other benchmarks were released but this is probably not the best representative.
Swift on server may not have "great performance", but compared to mainstream stuff it definitely has "pretty good performance" while still providing a somewhat nice language.
I guess the key selling point is, well, being able to use Swift on the server (some people do like the language). It is pretty useful for sure. Certainly not the only choice.
That Swift is compatible with almost nothing on Linux sounds strange, not sure what you mean by that. E.g. I find it particularly nice for writing Apache modules (the Swift C integration is really neat).
P.S.: While Apple puts minimal effort in anything but macOS and iOS, others put significant effort into Swift on Linux. Like IBM.
Compare this to Go (no major revisions after 6 years, probably a backwards-compatible major revision in 2-3 years) and Rust (no major revisions after 3 years, but with a mechanism called "editions"). To say nothing about Java or C#.