Today, there are a number of literals that we can either use the IDE to generate or type by hand, such as: let red = #colorLiteral(red: 1.0, blue: 0, green: 0)
.
Back in 2016, @Erica_Sadun pitched the idea to tidy up the syntax and add a bunch of new literals. I liked the idea, but it received some pushback for being too overreaching (that's my impression anyway).
This is a much more focused pitch with a pretty clear use case and precedent in other languages. Please let me know what you think. Would this fly as a proposal? Could you see yourself using this?
Background
Last year, Swift 4 introduced several nice features for string literals, namely the multi-line syntax. This makes hard-coding strings very convenient. In my experience, this is great for medium-length strings, but it gets unwieldy if the string is especially long or contains some kind of code.
It's easy to imagine an application that would have this kind of problem: consider a web server with dozens of SQL queries, all typed out as multi-line strings. It is more difficult to grok the SQL when it's all one color, plus it clutters up the Swift code around it if it's especially long. You could mitigate some of this by moving all the strings to constants in one source file, but that starts to get messy in its own way.
The same thing goes for HTML, markdown, and other such strings.
Proposal
To ease this pain, I'd love to see a new literal introduced that lets us embed the contents of another file as a static string.
For example, suppose we have the following Xcode project or folder structure:
Project
βββ Resources
β βββ long_query.sql
βββ Sources
βββ server.swift
Our server.swift
file might have a function that runs that "long query":
func execLongQuery() {
let sql = #stringLiteral(resourceName: "long_query.sql")
database.execute(sql)
}
This function is nice and short because we've hidden the SQL in its own file. It's easy to imagine how, without this, one's Swift code could quickly become overburdened with embedded SQL.
There is a literal that already exists which gives you the URL of a file. You could implement the above function using that instead:
func execLongQuery() {
let file = #fileLiteral(resourceName: "long_query.sql")
let sql = String(contentsOf: file)
database.execute(sql)
}
But, there is a subtle difference here. Since #fileLiteral
only gives you the URL at compile time, the program still has to load the contents of the file at run time. This behavior is a nonstarter for binaries that are performance-sensitive or don't ship as bundles β at least for this particular problem.
Today, the only solution is to embed the text in a multi-line string literal. But in some cases this is a real hinderance to your workflow. I think the #stringLiteral
syntax has some nice benefits:
- You get the contents of the file at compile time, removing runtime dependencies.
- Your Swift code is cleaner, since it isn't littered with long string literals. (Although this can always be overdone and introduce obscurity problems.)
- Using a separate file lets you use all the text-editing features you're used to, like syntax highlighting and autocomplete.
Notes
- There is precedent for this in other languages. The one I'm aware of is Rust where they have a compiler macro for doing this exact thing. I'm sure there are other examples.
- In Xcode, the
#stringLiteral
syntax would likely be hidden behind a nice icon as it is with#fileLiteral
,#colorLiteral
, etc. - SE-0039 β Modernizing Playground Literals
- Medium post showing how to use literals