Mandatory Disclaimer: This does not fall under the scope of Swift 3 timeframe as it is entirely additive
I love literals. Right now, in addition to the protocols that allow types to adopt literal expression, Swift offers three special literals: #colorLiteral(red:,green:,blue:alpha:)
, #fileLiteral(#imageLiteral(resourceName:)
, and #imageLiteral(resourceName:)
.
Literals do not have types. They are evaluated and their types inferred from the context in which they are used. For example:
I literally (sorry, pun intended) cut and paste the code from the iOS playground to the OS X/macOS playground.
The same source line (let color = #colorLiteral(red: 0.8100712299, green: 0.1511939615, blue: 0.4035313427, alpha: 1)
) established a UIColor
in one case and an NSColor
in the other. In both examples, the integer literal “1” resolved to Double
type inference.
Introducing language literals creates typeless universal representations that cross operating systems and exist independent of implementation details. Examples of these typeless concepts include numbers, file paths, images, and colors (not to mention arrays, truth values, etc).
So what can Swift introduce next?
While I’d love to see Bezier paths, I’m not sure there’s a way to do this cleanly. If you notice, in the existing literals, all fields are declared in the initializer. Although Bezier paths use essentially universal components, they require multistage creation.
A Bezier path consists of a series of move to, line to, quad curve to, cubic curve to, and close. (Other features like “remove all points” are simply gravy.) If Swift could offer a literal Bezier, at best it could construct a single empty instance, or a fixed set of predefined instances like an oval, square, line. Neither is particularly satisfying:
let myBezier = #bezierLiteral() let myBezier = #bezierLiteral(.oval, rect:)
There is, as far as I know, no such thing as a typeless method that would allow universal construction:
let myBezier = #bezierLiteral() myBezier.#bezierMoveTo(point:) myBezier.#bezierLineTo(point:)
You could work around this by limiting Bezier literals to load from common vector graphic formats stored in a file, just as #imageLiteral
now allows you to load graphics. If you really want to stretch, you could take that same approach to load style sheets, enabling you to construct attributed strings. (Or introduce #jsonLiteral
)
Moving to more reasonable and achievable goals, I think Swift could easily allow literals for core geometry (rects, points, sizes, vectors, transforms), that would apply across 2D and 3D applications, allowing you to use the same literals regardless of whether you’re using Quartz, Accelerate, GameplayKit, simd, and so forth.
I think Swift would also allow simple adoption of literals for sounds, URLs, and dates (at least those using the Unix epoch, rather than Apple’s epoch).
What other targets of opportunity can you think of that would simplify cross-platform development through Swift literals? Let me know.
@ericasadun add #fontLiteral to your list 😉
— Matthew Johnson (@anandabits) July 8, 2016
13 Comments
I’m curious why you don’t think an array-of-elements argument for Bezier literals wouldn’t work, where each element is an instance of a bezier-element enum:
let myBezier = #bezierLiteral([.MoveTo(0.0,0.0), .LineTo(0.0,1.0), .CurveTo((1.0,1.0), (0.0,1.0), (1.0,1.0)), .Close])
Thank you for this excellent post, Erica. I was wondering if the bezier syntax for the “d” attribute of the SVG element may be a way to go. For example `let banana = #bezierPath(M8.64,223.948c0,0,143.468,3.431,185.777-181.808c2.673-11.702-1.23-20.154,1.316-33.146h16.287c0,0-3.14,17.248,1.095,30.848
c21.392,68.692-4.179,242.343-204.227,196.59L8.64,223.948z)`
I had SVG in mind when I was writing about “common vector formats”
Of course. I thought you meant only, “common vector graphic formats stored in a file”. At any rate, I love the way you are framing your discussion on Swift literals in terms of “targets of opportunity … that would simplify cross-platform development”. Lots of food for thought. Thank you.
Are literal fonts or font styles exist yet?
I would love to see a literal for AttributedStrings! (top of my list!)
After that, I would like to see JSON literals.
Then sound.
Font also makes sense.
Not sure about dates. I can’t think of a time where I have hard-coded a date (and I once built a snazzy custom calendar control). I typically use now, today, tomorrow, etc…. If you could have literals for relative dates, then that would be useful, I think.
A bezierCurve literal would only really be useful with editor support (or when generated by things like Paint Code)
“Editor support” for shape literals of that sort is a really good idea!
I absolutely hate colour literals. It’s hard enough to read other people’s code sometimes without adding a feature that specifically reduces readability for the colourblind.
That’s a perfectly fair point and I think it would make sense for Xcode to offer alternative presentations *and* raw literal presentation. I think the goal of literals should be cross-platform code, not to be “cute”.
I think the cute shark was jumped when emoji were allowed
Sadly, Xcode 8 doesn’t warn you if your #imageLiteral no longer exist. IMHO, it’s useless without it.
Had the same conclusion and created a tiny script to make Asset Catalog safe again -> https://github.com/s4cha/AssetChecker
🙂 Hope it helps!