Jordan Rose Profile picture
He/him or they/them. Mac apps as @belkadan. Formerly Swift at Apple, now at Signal.
Dec 26, 2021 25 tweets 5 min read
Swift delight: Optional conveniences

Lots of languages have something like Optional, but it’s so commonly used that it’s worth adding dedicated features for. I’m going to run through a few of them here. Credit to @davezarzycki for reminding me that this is worth talking about. These weren’t on my original list because none of them originated with Swift, but they *are* relevant for someone designing a language with proper Optionals or even plain nullable types.
Dec 21, 2021 16 tweets 3 min read
Swift delight: `try`

I don’t mean the whole error handling model; there are definitely pros and cons there. I just want to focus specifically on `try`. That said, I do have to talk about the model a bit to establish what Swift does differently. There are essentially two classes of error handling implementation: caller-checked, and “zero-cost exceptions”. In the caller-checked model, after a function returns, the caller checks *something* to see if there was an error—the return value, a special out-parameter, something.
Dec 8, 2021 16 tweets 4 min read
Swift regret-ish: weak vars in structs

Currently this is the only way to have a collection of weak values without having one class per weak ref. But you have to manually filter it; it doesn’t auto-shrink when a reference goes away. Still, sometimes that’s what you want, so…this wasn’t on my original list. But @JensAyton brought it up because, like lazy vars, weak vars make a containing struct act weirdly. And it makes my regret/delight tick-tock line up better. So here we go.
Nov 24, 2021 10 tweets 2 min read
Swift regret: no open protocols

Sometimes you have a protocol that only makes sense for types in your module to conform to, but that you want to have as a generic constraint. “PropertyList” is a good example. Someone else cannot just make a new plist type. This is a @DevAndArtist appreciation thread, because they brought up this need back during the controversial SE-0117 discussions, which first made the public/open distinction for classes. github.com/apple/swift-ev…
Nov 21, 2021 9 tweets 2 min read
Swift regret: retroactive conformances

These are when you have a type Foo from module A, and a protocol Bar from module B, and you need Foo to conform to Bar. And so you say `extension Foo: Bar`. This should not be allowed. It’s super convenient, but it suffers from the “what if two people do this?” problem. I’ve written about this before. (Skip down to “Retroactive Modeling”.) forums.swift.org/t/why-you-cant…
Nov 18, 2021 20 tweets 4 min read
Swift delight: library evolution

In this case I don’t mean the feature for changing your library in binary-compatible ways, although that’s cool too. I just mean the general ethos of making library authors a priority. (If you *do* want to learn more about the binary compatibility -enable-library-evolution, check out the blog post from a few years ago.)

swift.org/blog/library-e…
Nov 10, 2021 13 tweets 3 min read
Swift mangling regret #3: private discriminator mangling

One of the fundamental things about `private` is that other files’ source shouldn’t be affected by a `private` declaration, at least not directly. That doesn’t *sound* like a mangling problem though… Note: in this thread I’m going to use “private” to mean “file-private”, including both `private` and `fileprivate` in Swift. This is partly for simplicity and partly because I still think they shouldn’t have been separated. See github.com/apple/swift-ev… and github.com/apple/swift-ev….
Nov 10, 2021 4 tweets 1 min read
Trying out Serial Experiments Lain (1999) for the first time, and spotted this interesting frame of real C code. There's a "typo" for one thing: that top line should be "%c>%c¥n" rather than "%c%¥n", judging by what's below. But what's up with that ¥? It's because… A teacher writes C code on ... …the most common Japanese codepage pre-Unicode, Shift-JIS, is *nearly* compatible with ASCII, except it has a yen sign ¥ instead of a backslash \ at position 0x5C. So you'll find perfectly normal C source files (and Windows paths) that use ¥ instead of \.
Nov 9, 2021 4 tweets 1 min read
When I was younger I could sleep as late as I wanted to, so “fall back” was the “good” DST change where it was easier to wake up on time, and “spring forward” was the hard one. Now the light wakes me up and yet we’re not going to bed early anymore, so fall is the hard one. All this is to say: yes, abolish DST. I have a mild preference for permanent summer hours over permanent winter hours but that’s not the important part.
Nov 5, 2021 14 tweets 3 min read
Swift mangling regret #2: there are two mangling schemes and we may never be rid of the first (on Apple platforms).

What is this treachery? I thought mangling was part of the ABI, and there wasn’t a stable ABI until Swift 5! The explanation is a chain of decisions and features… One feature that Objective-C has that’s still unstable in Swift is looking up a class by its name. Several parts of Cocoa rely on this, especially in xib files, so we had to support it in Swift 1.0.
Nov 3, 2021 15 tweets 4 min read
Swift regret: no mangling for library evolution

“Name mangling” is the process of coming up with a single string that uniquely represents an entity in a program. Swift uses this for symbol names, identifiers within SourceKit, and even as a compact type description format. I’m going to focus on the “symbols” part, though, which is how a reference in one module gets resolved to a definition in another. If the library can be swapped out at run time, the mangling scheme also has to be consistent across library and compiler versions.
Oct 6, 2021 12 tweets 3 min read
Swift regret: how C enums get imported

This is another of those “there’s a right answer but it’s too late to change it” issues. The problem is that C enums have way fewer guarantees than Swift enums. C enums are basically glorified integer constants. You can even assign a case directly to an int without casting. So naturally, people used them for all sorts of things beyond “mutually exclusive values”. Especially in Old C before `static const` was a thing.
Oct 1, 2021 17 tweets 3 min read
Swift delight: value semantics collections. Classes have reference semantics, structs made of primitives have value semantics, and structs made of collections *can also have value semantics*. And I can pass a collection around without worrying about someone modifying it. Python has this pitfall that trips up newcomers where a default argument is evaluated only at function definition, not function calling, and so a default list *persists* across calls even if you modify it.

def contrived(lst=[]):
lst.append(5)
return lst
Sep 29, 2021 10 tweets 2 min read
Swift delight: guard. I was never interested in `unless`; `if !foo` never bothered me. But you can’t negate pattern-matching in the same way, and Swift’s `if let` was a form of pattern-matching specific to Optional. (Arbitrary pattern matching outside of `switch` is performed with `if case`, so the full form of `if let foo = maybeFoo` is `if case .some(let foo) = maybeFoo`, sugared to `if case let foo? = maybeFoo`.)
Sep 24, 2021 9 tweets 2 min read
Swift regret: inferred types for globals and stored properties

In Swift, as in many other statically-typed languages these days, you can say `var x = 5` and the compiler figures out that `x` is an Int. That’s fine. Sometimes this is extremely useful, for types like `LazyFilterSequence<Slice<RingBuffer<Int>>>`. (Though I can hear the non-generic language folks saying “types dreamed up by the utterly deranged!”) Most of the time, a local’s type is clear enough from its name and use.
Sep 22, 2021 12 tweets 3 min read
Swift regret: implicit initialization of Optional variables

In Swift, stored properties and local variables aren’t initialized by default; the compiler makes you do it. Unless it’s Optional and mutable (var, not let). I don’t think I’d have bothered to elevate this to the list if it didn’t manage to cause *performance* problems, somehow. (The fact that a stored property is initialized to nil shouldn’t necessarily be exposed to clients.)

forums.swift.org/t/what-is-a-va…
Sep 17, 2021 4 tweets 1 min read
Swift regret: subscript trailing closures.

Wait, what?

bugs.swift.org/browse/SR-6157 Remember how I said subscript indexes have all the fancy features of function arguments? We implemented that by having them share code in the parser, where calls look for “()” and subscripts for “[]”. And we forgot to turn off the trailing closure part for subscripts. That’s it.
Sep 15, 2021 7 tweets 2 min read
Swift regret: subscript argument label rules

I bet a lot of people don’t know how flexible subscripts are in Swift. The reason they’re declared with function-like syntax is because the index part really is a parameter list. You can have labels. Multiple params. *0* params, even. But if you want labels, you have to say so explicitly:

subscript(at path: String)

even if the label is the same as the argument name:

subscript(path path: String)

Why are subscripts different in this way?
Sep 10, 2021 5 tweets 2 min read
Swift Regret: unapplied instance methods

Once again I don’t have to write this one up, because @jckarter already did. In a proposal. That was accepted!

Sometimes time constraints really stink.

github.com/apple/swift-ev… @slava_pestov called this one out earlier in the week, too. And the two are linked, actually! At one point SIL modeled `object.process(arg)` as something like `type(of: object).process(object)(arg)`. The curried signature makes the types line up.

Sep 8, 2021 8 tweets 2 min read
Swift Regret: bound methods. You know, saying something like `object.action` without calling it. This isn’t some grand mistake, just a feature that’s turned out to be less useful and more problematic than anticipated. There are a few problems with this. One of them is that Swift supports overloading, so `.action` might be ambiguous. You can control type-based overloading with additional type context, and name-based by using full names (`append(_:)` vs. `append(contentsOf:)`).
Aug 30, 2021 25 tweets 5 min read
Swift regret (and this is a big one): type-based overloading

When we were first developing Swift, many of the mainstream languages had type-based overloading (C++, Java, C#), and many didn’t (C, Python, Objective-C). How did Swift end up with it? The previous regret was an ObjC feature that got pulled into Swift. This one’s a place where I think ObjC got it right, most recently brought up by @eschaton.

[weekend Swift regret cause I only did one last week]