10 years on, what would you change about Swift?

Smalltalk is not really a programming language, it’s an open-ended retro graphical adventure game.

For anyone who wants to get into language implementation, I highly recommend the Smalltalk Blue Book from 1983. Even though it’s ancient history now, it’s still as good as any introduction to the design of a bytecode VM with dynamic method dispatch and garbage collection. The discussion of bitmap graphics is dated but the algorithms are cute.

10 Likes

The improvements in this area are very recent, a year ago would have been painful at best, if not impossible.

You can see here if you're interested, it's not much different from C now: swift/docs/EmbeddedSwift/UserManual.md at main · apple/swift · GitHub

Yeah. While I’d like to change several things, the biggest bang for the buck I think would be more explicit library/module namespacing and import/export control.

I keep on wishing we had the Dylan system, where

  • libraries are the compilation unit,
  • they are comprised of modules
  • libraries can import specific modules from other libraries
  • libraries can contain modules that are not exported
  • modules can import symbols from other modules wholly or individually and can exclude symbols
  • modules can prefix and rename the symbols they import
  • modules can export their own symbols and re-export imported symbols
  • imported symbols are directly added to the importing module flat
  • module and library specs are nicely analogous to header files—a good place to get a overview of their capabilities
  • “private”, “public”, etc. aren’t keywords (though I do like “public” as something like a comment for scanability and awareness)

That solves audience-specific SPI, name collisions, module name conflicts, collections of related symbols, and combining internal complex modules together in to one simplified product module, in one tidy and elegant system.

But everyone is so dead set on the public/private/protected approach which doesn’t scale and honestly sucks.

4 Likes

It's true up to a point. It's also about how much abstractions and overhead you can bypass when you need more performance.

It also depends on how optimized fundamental types are implemented:

And you can detect those thanks to benchmarks.

Another explanation could be that most of what you can do to make Swift fast is only known by Apple Engineers and undocumented unlike C++.

It sounds a lot like you’re talking about C++, and maybe C11 or later. Or perhaps you’re talking about BASIC, FORTRAN, COBOL, LISP, Algol, Modula, Simula, B’s evolution to C, or even something more obscure?

I first learned C++ 30 years ago, before it was standardized, and even after using it daily in my work for more than half that time (including 12 years at Apple), I’ve never learned the whole thing, because it’s a constantly-moving target that keeps snowballing while you’re trying to get real work done. That’s the problem I’ve seen happening with Swift over the past decade. When it first came out (while I was at Apple), I was really excited about it, aside from the C-style method call syntax.

In reality, a lot of great programs were written with those flawed languages, like Objective-C, and most of the time, the perceived shortcomings were really not as much of a problem as they may seem, and programming really wasn’t that hard.

Maybe I’m just getting too old, but I feel like maybe you’re someone who is too close to Swift to see the problem, as it seems you’ve been keeping pace with the language evolution over the past decade.

I feel sorry for anyone attempting to learn the language now, as it is really a monumental task, second only to learning the entirety of C++.

I always thought Smalltalk was amazing, by the way.

6 Likes

A performance hints documentation with good patterns and how to properly dip down into unsafe primitives when needed would be a nice addition (there is an older document along those lines but I believe there’s more to be added to that…There is also @taylorswift comments and links here - of course there’s always the risk that it’s being cargo culted, but I sincerely believe it would be great to try to summarize such known performance quirks.

Perhaps we should just open a performance GitHub repo where we can collaborate on that as a separate thing - together with benchmarks proving the patterns usefulness - if there’s interest we (Ordo One) could probably set that up.

10 Likes

Nah, don't feel like a true statement, C++ is something another level, mostly because as @Slava_Pestov stated due to unsafe nature.
As soon as you know some basics of imperative and functional programming would say Swift is quite straight forward, it's not even so hard then to jump to Rust, Scala, Kotlin and etc. Of course there are details, especially in memory management, but then you just read the documentation and in most cases it's clear.

Tbh it's actually true that it's hard for newcomers sometimes, but then would be nice to know what features are exactly making it complex and make people struggle, so this can be addressed. In the end topic of discussion is what would you change?

6 Likes

Honestly, I would get back to Swift 3-4. I was very excited about Swift when it was only released, it looked much more concise and convenient comparing to Objective-C, but recently, after some time of writing objc code at my job, I returned to Swift and it felt extremely verbose and overcomplicated with all these latest features. I did not struggle with callbacks or writing guard let self = self, but I do get tired of endless some X, any X. Now I can't understand what I'm going to benefit from using Swift, sadly.

2 Likes

Swift evolves and becomes... more complete? It offers a lot of tools, most of which are coherent and play nicely together. And, as in many languages, its features are quite often opt-in, if you are OK not using existentials a lot, you just don't use them.

It is important, I think, to not confuse Swift itself with what we get in Apple ecosystem with, say, SwiftUI. The latter is actually quite complicated to get yourself around in details, but in overall still a huge improvement for a significant part of the needs. Yet this is a framework for iOS/macOS/etc. family, not Swift itself.

Finally, too simple language has its own limitations. Take GoLang as an example: extremely simple language. That simplicity can be beneficial, because it is actually almost impossible to overcomplicate things there. Yet it lacks expressivity for some cases that Swift has, for example, with its type system. Or still exposing nil pointers. I think too simple language would be either not useful at a larger scale than one small subset of problems, or expose more unsafety to the user (and of course there is always C++ good at being unsafe and complex :smiley:).

The current explosion of language capabilities is mostly has been driven by the new concurrency, covering a lot of missing spots along the way in related features. For example, I've been missing current improvements over existentials & generics since Swift 3, and having them right now have enabled to remove tons of erasure types.


Within previous discussion, I am huge +1 on the:

  • Improving documentation and examples that has been put in this discussion previously. Performance optimisations can be hard to understand, or a file reading example.
  • For the next versions it would be probably a good idea to slow down a bit and consider adding new features more strictly. It is always tempting to add more features to the language, but not always the best way. More focus on stdlib might be better, providing more tools for basic needs.
4 Likes

I’ve never felt that Swift is (or becoming) too complex. However, I do wish there was more comprehensive and detailed documentation, complete with examples, motivations, and technical backgrounds for every added feature. This would not only help in understanding the features better but also in gaining deeper insights into the language itself. Relying solely on pitch and proposal threads makes it challenging to keep up.

16 Likes

I wasn't referring to anything in particular; while I'm vaguely familiar with those it's out of curiosity, I never got to use any of them (other than C and C++ of course).
My ability to understand the circumstances in which C++ and others evolved is limited because I don't have the context of why certain decisions were made at the time, I can only compare my experience of learning the languages now.

I started learning Swift as one of my first languages about 3 years ago, and while I did find Swift difficult to learn it was difficult in a good way — I was learning a lot of valuable ideas that actually transfer over to other languages really well.
On the other hand with languages like C++ it felt much more like I was learning language specific patterns that work around issues I didn't yet understand (and shouldn't need to worry about in the first place).

4 Likes

I think the intention behind the Substring type is to make it very clear that you're dealing with a lightweight (and short-lived) view into a String, not an actual String.

1 Like

Glad if you think it becomes more complete. I have the directly opposite opinion here, that it gets less and less complete because the amount of features/syntax variations grows, but their interaction with each other becomes less.

And it cannot be disabled in a project. For instance, how do you suggest to not use existentials? Do not create protocols and use base classes/concrete types?

2 Likes

Interesting, I have the exact opposite experience. I come from Obj-C then started to use Swift day one.

And learning some C++ made me understand how things work, the design choices made in Swift and other programming languages, their trade offs, implementation details, etc.

Thanks to C++ being low level, focused on performance and exposing everything, I am able to reuse all the things I learnt from C++ with other programming languages.

3 Likes

Honestly, except for the problems it directly inherited from C, most of C++'s difficulty is a combination of WG21's fetish for making language features into library features and new features randomly breaking when used with a combination of other older features that's exactly a common enough combination to make you pull your hair out.

2 Likes

Using protocols doesn't imply having to use existentials. Protocols are an essential part of Swift, you couldn't disable them without breaking the language as even something as simple as an Int uses them.

foo(_ a: some FooProtocol) is sugar for foo<T: FooProtocol>(_ a: T) so it's actually a lot less verbose than the alternative. No existentials are required, and the performance difference can be significant :slight_smile:

I think this video from wwdc may be helpful to you Embrace Swift generics - WWDC22 - Videos - Apple Developer

6 Likes

Can't agree more with you. Feel the same.

1 Like

Don’t know if it was mentioned before, but I would have really liked the default array subscript returning Optional<Element>, similar to the subscript on Dictionary, i.e array[0] // Optional<Element>
Alternatively, Swift could expose an unchecked version of the “safe” subscript, which would require the developer to be explicit i.e array[unchecked: 1] // Element providing the same implementation as the current default subscript.

4 Likes

I remember reading Usenet discussions of a similar nature after Apple acquired NeXT. A lot of great programs were written using the Mac Toolbox API, Objective-C is too complex, and the shortcomings of classic macOS are not as much of a problem as they seem for anyone with a little bit of real world experience (memory protection is just a crutch for sloppy coding, etc).

I think a lot of people don’t remember how controversial OS X and Cocoa were when first introduced. It killed off an entire cottage industry of UI extensions/Finder widgets/neat hacks that relied on unrestricted patching of arbitrary system code (there was even a third party re-implementation of virtual memory you could buy); the increase in resource usage was astronomical from the Unix kernel/objc runtime/Aqua GUI; and the original plan — to support the toolbox API in an emulator form only — was changed at the last minute, with the Carbon compatibility API introduced as a stop-gap after major vendors basically threatened to stop supporting the platform.

In comparison, the introduction of Swift to the platform just adds some new shared libraries you can link against.

21 Likes

I wonder how many complained when System 7.5 became 32-bit safe.

3 Likes