[swift-evolution] Proposal: String literal suffixes for defining types

Joe Groff jgroff at apple.com
Fri Dec 11 16:38:13 CST 2015

I was a little disappointed something like this didn't already work:

struct Foo: StringLiteralConvertible { var f: Foo { return self } }
struct Bar: StringLiteralConvertible { var b: Bar { return self } }

"x".f // currently a failed lookup in String; could produce a Foo
"y".b // same, for Bar


> On Dec 10, 2015, at 11:07 AM, Kevin Ballard via swift-evolution <swift-evolution at swift.org> wrote:
> The fact that Swift uses the exact same syntax ("a") for String, Character, and UnicodeScalar can get annoying at times. When unconstrained it's always String, and the only way to disambiguate between the two when used in a context that takes both Character and UnicodeScalar is to explicitly constraint it further, e.g. with `"a" as Character`. A trivial example of this in action is
> var s = ""
> s.append("c")
> This code looks pretty straightforward, but it throws an ambiguity error (and the annoying part is, it doesn't actually matter which way it's resolved, the behavior is the same).
> Having to type `"c" as Character` and `"c" as UnicodeScalar` can get pretty annoying if you have to do it a lot. It would be great to reduce this typing a bit.
> My initial proposal here is to introduce string literal suffixes. Let me type something like `"c"c` for a Character and `"c"us` for a UnicodeScalar (and maybe `"c"s` to explicitly mean a String, although that's the default if unconstrained). AFAIK this is not ambiguous with the current syntax, as I don't believe it's ever legal to put an identifier like that after a string.
> Ideally this could be extended by library code with new suffixes. The obvious way to do that is to allow for a new type of "operator" declaration, perhaps something like `literal operator c { type Character }` (where `literal` is a context-sensitive keyword), which declares the suffix and the type (the actual type construction will be done with StringLiteralConvertible, StringInterpolationConvertible, UnicodeScalarLiteralConvertible, or ExtendedGraphemeClusterLiteralConvertible). If the same suffix is declared in two different modules that are imported into the same program, they're unambiguous within their source modules, and within the parent module using the suffix operator will be ambiguous unless further constrained (e.g. similar to using a function that's overloaded on its return type).
> One possible library use for this would be something like `"^\s*foo"r ` for a regular expression (although regular expressions probably also want some sort of "raw" string literal syntax to deal with escapes, but that's orthogonal to this proposal).
> Syntax is up for debate. I picked postfix characters because I believe it's ambiguous and it has precedent, both in C's numeric literals, and in C++11's user-defined literals (although C++11 has a required underscore before the literal, I believe this is just to allow C++11 to define its own new suffixes without ambiguity). This syntax could also work for numeric literals, come to think of it, with the same declaration and using IntegerLiteralConvertible or FloatLiteralConvertible. Heck, it could work for array and dictionary literals too, though that's less likely to be useful.
> FWIW, Playground color and image literals have the form [#Color(colorLiteralRed: 1, blue: 0, green: 0, alpha: 1)#] and [#Image(imageLiteral: "hi.png")#]. These are interesting, but don't solve the original problem (of having to type out the full type name) so this syntax is not appropriate for this feature (but the syntax is fine for what Playgrounds use it for, which is to embed literal colors/images into the source code).
> -Kevin Ballard
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

More information about the swift-evolution mailing list