Swift Regret: "Double" rather than "Float64"

Part of the Swift Regrets series.

Swift has “Float” and “Double” rather than “Float32” and “Float64”. “Float” hasn’t been the floating-point type to use by default in decades, but you can’t name Float64 “Float” while ubiquitously importing C APIs. The name “Double” is a historical quirk that doesn’t say what the type is at all. We ended up not wanting to deviate from C, but I really think it would have been fine to use “Float32” and “Float64”; we just didn’t spend much time on it. (Rust uses “f64” and Go uses “float64”.) The name ‘Float’ would then be an unavailable alias for Float32 to get you into Swift style.

It turns out that both Alex Johnson and David Sweeris suggested this back in the Swift 2 days, but we didn’t end up changing it. :-(

This is also a good time to remind people that unlike integers, there’s no direct benefit to floating-point values matching the platform CPU register size, and that most of the time you should just use Double even on 32-bit platforms. The existence of CGFloat on Apple platforms is a proxy for screen sizes and available memory, not a general recommendation. (Of course, if you have tight memory constraints, or are working with SIMD or GPU APIs where you can trade off precision for speed or throughput, you may want to use Float instead, or even Float16. But even then, consider doing your calculations as Double and converting back to Float or Float16 for storage.)

I’ll share that there was much more discussion around Int, the type ultimately defined primarily as “pointer-sized” and secondarily as “machine register”. The biggest reason was probably to match NSInteger, the currency type in Apple’s APIs then. But making Int Int64 everywhere (as a typealias, maybe?), would have meant fewer naive overflow errors and fewer 32/64 portability issues.

Unfortunately this discussion happened so long ago I forget more of the pros and cons we thought of. I think it worked out okay in the end!

Since we did change Int, some people wondered why we couldn’t have changed Float as well (to mean Float64). I think part of the reason was that Apple had already moved to NSInteger, but it was still a pain in cases that really did talk about “int”, like NSNumber. (Those APIs eventually got NS_SWIFT_NAMEd to match Swift.) For Float, though, we would have had to additionally deal with things like logf and sinf, and UserDefaults.double(forKey:), and…well, it wouldn’t have been impossible, but it would have been harder than making a clean break with Float32 and Float64.