[swift-evolution] multi-line string literals.

John Holdsworth mac at johnholdsworth.com
Sun Apr 24 20:41:18 CDT 2016


To audition Xcode using the following multi-line syntax:

        let xml = "<?xml version=\"1.0\"?>
            "<catalog>
            "   <book id=\"bk101\" empty=\"\">
            "       <author>\(author)</author>
            "       <title>XML Developer's Guide</title>
            "       <genre>Computer</genre>
            "       <price>44.95</price>
            "       <publish_date>2000-10-01</publish_date>
            "       <description>An in-depth look at creating applications with XML.</description>
            "   </book>
            "</catalog>
            ""
        print(xml)

You can install:  http://johnholdsworth.com/swift-LOCAL-2016-04-25-a-osx.tar.gz <http://johnholdsworth.com/swift-LOCAL-2016-04-25-a-osx.tar.gz>

> On 24 Apr 2016, at 23:35, Chris Lattner <clattner at apple.com> wrote:
> 
> 
>> On Apr 23, 2016, at 2:08 PM, Brent Royal-Gordon via swift-evolution <swift-evolution at swift.org> wrote:
>>> I’m trying to avoid more advanced features such as the handling of indenting which
>>> for me complicates something that if kept simple can be documented very easily.
>> 
>> I don't think you can tackle multiline strings without worrying about indenting. Indentation may fundamentally change the approach you choose.
> 
> I agree with this and almost every point you make in your email (and your other subsequent one about one approach maximally general).  That said, I wonder if there is a different conclusion that can be reached.  I’m going to rearrange your three features a bit:
> 
>> The way I would prefer to tackle these is:
>> 
>> * Multiline literals: If the closing quote of a string is not present, look at the next line. If it consists of (optional) indentation followed by a matching opening quote, the string has a newline and then continues after the quote on the next line. (The handling of comments is an open question here.)
>> 
>> 	let xml: String = "<?xml version=\"1.0\"?>
>> 				"<catalog>
>> 				"\t<book id=\"bk101\" empty=\"\">
>> 				"\t\t<author>\(author)</author>
>> 				"\t</book>
>> 				"</catalog>"
>> 
>> The cool things about this are that (a) the compiler can tell you really do mean this to be part of the literal and you haven't just forgotten to close the string, and (b) there's no guesswork about how indentation should be handled. The uncool thing is that you need to insert the quote at the beginning of each line, so you can't just blindly paste into a multiline literal. Editors can help make that easier, though—a "paste as string literal" feature would be a nice addition to Xcode, and not just for multiline strings or just for Swift.
> 
> Yes, I completely agree.  This is is awesome, and a nice & simple generalization of our existing syntax.  It has obvious behavior even if you encounter it in code without knowing about the feature.
> 
>> * Disabling escapes: If you use single quotes instead of double quotes, backslash escapes are disabled.
> 
> We need a way to disable escapes, but it seems to me that (since it is orthogonal to the other concerns) that it should not be tied to the “multiple single quotes” syntax.  What is your thought on “modifier” prefix characters for string literals?  e.g.:
> 
> 	let x = e”no \escapes \(processed here”
> 
> If we supported these, they would be supported with multi-line string literals by putting the modifiers on the first line of the literal, and the multi-line approach above would “just work”.  You could introduce several different modifiers, e.g. one that disabled general escapes, but still allowed \(x) for substitution.  
> 
>> * Yes, with a number of backslashes matching the number of quotes, which allows you to insert literal \( text: '''		<author>\\\(author)</author>
> 
> Egads!
> 
>> Notes on alternatives:
>> 
>> 1. If you wanted to not provide no-escaping strings, an alternative would be to say that *all* escapes require as many backslashes as there are quotes in the string delimiter. Thus, a newline escape in a `"""` string would be `\\\n`. This would in practice give you the same flexibility to write a literal without worrying (much) about escaping.
> 
> I’m really not a fan of requiring “stacking” of escapes to re-enable them.  This (IMO) just makes it less likely that you’ll run into an edge case.  I also don’t like the “fix" being to have to use 5 quotes around your strings :-)
> 
>> 3. It might be useful to make multiline `"` strings trim trailing whitespace and comments like Perl's `/x` regex modifier does.
> 
> If you have modifier characters already, it is easy to build a small zoo full of these useful beasts.
> 
>> * Alternative delimiters: If a string literal starts with three, or five, or seven, or etc. quotes, that is the delimiter, and fewer quotes than that in a row are simply literal quote marks. Four, six, etc. quotes is a quote mark abutting the end of the literal.
>> 
>> 	let xml: String = """<?xml version="1.0"?>
>> 				"""<catalog>
>> 				"""\t<book id="bk101" empty="">
>> 				"""\t\t<author>\(author)</author>
>> 				"""\t</book>
>> 				"""</catalog>"""
>> 
>> You can't use this syntax to express an empty string, or a string consisting entirely of quote marks, but `""` handles empty strings adequately, and escaping can help with quote marks. (An alternative would be to remove the abutting rule and permit `""""""` to mean "empty string", but abutting quotes seem more useful than long-delimiter empty strings.)
> 
> I agree that there is a need to support alternative delimiters, but subjectively, I find this to be pretty ugly.  It is also a really unfortunate degenerate case for “I just want a large blob of XML” because you’d end up using “"” almost all the time, and you have to use it on every line.
> 
> For cases like this, I think it would be reasonable to have a “heredoc” like scheme, which does not allow leading indentation, and does work with all the same modifier characters above.  I do not have a preference on a particular syntax, and haven’t given it any thought, but this would allow you to do things like:
> 
> 	let str = <<EOF
> <?xml version="1.0"?>
> <catalog>
> \t<book id="bk101" empty="">
> \t\t<author>\(author)</author>
> \t</book>
> </catalog>
> EOF
> 
> for example.  You could then turn off escaping and other knobs using the modifier character (somehow, it would have to be incorporated into the syntax of course).
> 
> I generally agree with your down thread remarks about how Swift doesn’t like to have multiple different solutions for the same problem.  OTOH, you could look at “” syntax as being analogous to closure exprs, and heredoc syntax as being analogous to nested functions :-)
> 
> -Chris
> 
> 
> 

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


More information about the swift-evolution mailing list