[swift-evolution] [Review] SE-0168: Multi-Line String Literals

Brent Royal-Gordon brent at architechies.com
Tue Apr 11 19:01:02 CDT 2017

> On Apr 11, 2017, at 7:33 AM, Vladimir.S via swift-evolution <swift-evolution at swift.org> wrote:
> 1. "Tripled string literals support backslash escapes and interpolation as normal, except that you can also place a backslash immediately before a newline. This indicates that the newline is merely for code formatting and should not be present in the resulting string:"
> - I think this a confusion point which should not be in this proposal. Currently in "normal" strings we just can't have single backlash as it will generate "invalid escape sequence in literal" warning.
> Is this feature worth the added complexity? I'm not sure currently.

I should probably explain this feature a little better, but basically, it's there for two reasons:

1. It lets you suppress the trailing newline that this feature would otherwise add.

2. It lets you use multi-line string literals for strings which don't inherently have newlines in them, but which are long, so you want to hard-wrap them.

Let me explain that second one in more detail. Suppose we decide to reimplement Swift in Swift, and your job is to port the table of diagnostic messages. Some of these messages are pretty long. For example, here's one:

	        "checking a value with optional type %0 against dynamic type %1 "
	        "succeeds whenever the value is non-'nil'; did you mean to use "
	        "'!= nil'?", (Type, Type))

You decide to model the diagnostics as an enum:

	extension Diagnostic {
		enum Message {
			case isExprSameType(from: AST.Type, to: AST.Type)

And now you want to write the actual error message. But this is a pretty long string. The project's coding standards requires that lines not get too wide, but you don't want actual newlines to be in the resulting string.

We think you should be able to write your code like this:

	extension Diagnostic.Message: CustomStringConvertible {
		var description: String {
			switch self {
			case .isExprSameType(let from, let to):
				return """
					checking a value with optional type \(from) against dynamic type \(to) \
					succeeds whenever the value is non-'nil'; did you mean to use '!= nil'?\

You are using the (hopefully familiar) multiline string syntax and its (hopefully familiar) indentation support; you're just backslashing the newlines to indicate you don't really want them.

Now, one alternative to support this use case is to make newlines non-significant by default—if you wanted a real newline, you'd need to backslash it (or perhaps use `\n`). But that's no good because (a) we think significant newlines are the more obvious semantic and will be more common, and (b) when you're using non-significant newlines, you really care about the whitespace before the newline anyway. In this example, there's a space before one of the two backslashes; the string would not render correctly without that space. The backslash at the end of the line makes that whitespace visible and protects it from overzealous tools (like Xcode with certain settings enabled) which like to trim trailing whitespace from lines.

So, I think escaped newlines are a small but important tool that makes this feature applicable to more use cases. And I don't think they'll confuse users.

Brent Royal-Gordon

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170411/c66b48d7/attachment.html>

More information about the swift-evolution mailing list