Optional dictionary subscripts

I admit I have not been following this closely and have not read all proposals and counter proposals and concerns - but of course that isn’t going to stop me from tossing out my own suggestion!

My idea starts with this:

let code = string // some code that we are generating
         + string and some more code here
         + string another line here
         + string
         + string including a blank line if we wanted
         + string etc.

When used in this way, it simply generates a string literal from everything that follows “string” up to and including the newline. To chain multiple lines together, it just uses string’s normal + operator. This would be the same as writing the following code:

let code = "// some code that we are generating\n"
         + "and some more code here\n"
         + "another line here\n"
         + "\n"
         + "including a blank line if we wanted\n"
         + "etc.\n"

I would then extend this to support some other useful approaches such as:

string(THE_END)
blah blah blah \\\ blah
  can be anything \o/
what ever!!
THE_END

Or to use the entire contents of an external file:

string(“file.txt")

l8r
Sean

···

On May 5, 2016, at 3:51 PM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

It had the idea that maybe the motivation behind continuation quotes is to make using multiline strings harder to use; in order to discourage their use at all.

Absolutely not, and frankly I resent the implication.

I'm looking at a space where (in my opinion) all existing designs are ugly and inelegant and trying to find something better. There are *reasons* Swift 2 doesn't allow newlines in quote marks; I'm trying to address them, not ignore them. There are nasty formatting problems; I'm trying to solve them, not tolerate them. There are significant context-sensitivity issues; I'm trying to fix them, not punt the problem to a syntax highlighter that is absent or incorrect in half of our tools.

Here's a piece of code-generating code I once wrote, ported to this prototype:

  https://gist.github.com/brentdax/8a8ee1f6028230f68ed85b7f3ebc95bf

(The actual code generation starts on line 93.)

And here's the same code in (beta-era) Swift 2:

  https://github.com/brentdax/WebResponder/blob/master/WebResponderCore/WebResponderCore/codes2swift.swift

I think the new version is an improvement over the old. I think I like it better than I would with `"""` or heredocs forcing things against the left margin. I think it's nice that I can look at any line—out of context, random access—and see which parts are string literals. I think if I want to add a doc comment to each of the constants it generates, I have to do a little awkward code shuffling, but the result is worth it:

  for statusLine in statusLines {
      code += " /// The HTTP \(statusLine.code) \(statusLine.message) status, used with `HTTPResponseType.status`.
               " \(statusLine.constant)
               "
               ""
  }

Overall, I find this code a lot more pleasant to read than it was in Swift 2, and somewhat more pleasant than it would be with `"""` or a heredoc. Maybe you don't agree; maybe you'd rather import some other language's warts. I understand—those warts come with convenience advantages, and you might prefer that convenience to the other things.

But at least have the basic respect for opposing viewpoints not to impugn my motives because you disagree with me or don't like what I suggest. That is just not nice.

--
Brent Royal-Gordon
Architechies

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I think that is another one of the advantages of using the continuation quotes.

···

Sent from my iPhone

On May 5, 2016, at 4:51 PM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:
  
I think it's nice that I can look at any line—out of context, random access—and see which parts are string literals.

If we use triple quotes (i.e. """) at the beginning of the multi line string literal and again at the end, it seems very unlikely that the heredoc notation would be needed.

I would simplify and remove the heredoc alternative from the proposal.

Also, for those of us who like the continuation quotes, I think the continuation quotes could be optional. For example this:

let html = """<html>
    ". <body>
    " <h1>\(title)<h1>
    ". <p class="fancy">A paragraph.<p>
    ". </body>
    "</html>
    """

would be equivalent to:

let html = """<html>
    . <body>
         <h1>\(title)<h1>
    . <p class="fancy">A paragraph.<p>
    . </body>
    </html>
    """

What do you think?

···

On May 5, 2016, at 2:13 PM, L Mihalkovic via swift-evolution <swift-evolution@swift.org> wrote:

On May 5, 2016, at 12:30 PM, Michael Peternell via swift-evolution <swift-evolution@swift.org> wrote:

Hi,

it's not a secret that I'm not a big fan of the proposal. The third draft doesn't change this and it's unlikely that any future draft will, because for me, the problem are the continuation quotes, and for Brent it seems like they are a must-have-feature (correct me if I'm wrong.)

I just wanted to say that I have drafted a proposal that solves the issues that I have encountered. (It's here: [swift-evolution] multi-line string literals proposal )
- it allows pasting text as-is
- it allows creating string literals where leading space on each line is stripped (while keeping indentation differences intact)
- it allows creating string literals where leading space on each line is not stripped
- optionally it allows strings to be raw, without any string interpolation or escaping whatsoever
- in none of the literals you have to write "<book id=\"bk101\" empty=\"\">", you can just write """<book id="bk101" empty="">""". This also lets you copy&paste text out of the program source and back into a HTML file.

It had the idea that maybe the motivation behind continuation quotes is to make using multiline strings harder to use; in order to discourage their use at all. Two points to consider:
- people who don't want to use MSL will not, even if you throw Python-like """multi-line strings""" at them.
- people who want to use them do it, even if there is no MSL available. I saw that in Objective-C, with multiple lines of HTML and CSS wrapped into a big multiline objc-string-literal and thrown at a WebView. I could send the literal to the console before sending it to the WebView and it was basically unreadable. I eventually refactored it to put the thing into a file (also because the HTML grew in space, and the inline-literal became impractical)
- my most important point: if someone uses multiple lines of HTML or CSS or XML directly within the code, I want it to look okay. I don't want an MSL feature that is so unwieldy that people voluntarily not use it; it would be better to have no MSL at all.

I don't think that multiline strings are a must-have feature for a language, because they are not used very often. (I included an example of a good use case in my proposal.) I acknowledge that in many programming cases it would be better to not put a huge pile of text directly into the source, but to load the text from a file at runtime. But even when these MSL are misused, I prefer to read a """python multiline string""" over a "concatenated\n"+"Java\n"+"String".

-Michael

Hi Michael. hope this helps Markdown formatting for Michael's string literal proposal · GitHub

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Adapting the original proposal if you’re not a fan of continuation quotes..

It’s possible to have a multiline “””python””” multi-line string but tidily indented.
As suggested earlier in this thread the lexer can strip the margin on the basis of
the whitespace before the closing quote as per Perl6 (This could be a modifier “I”
but might as well be the default TBH.) Would this be the best of both worlds?

        assert( xml == i"""
            <?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>
            ""” )

Other modifiers can also be applied such as “no-escapes"

        assert( xml != ei"""<?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>
            """ )

I’d hope this would satisfy any need for <<HERE/<<‘HERE’ style constructs.

Or you could support both continuation and indented python style:
http://johnholdsworth.com/swift-LOCAL-2016-05-05-a-osx.tar.gz

John

···

On 5 May 2016, at 14:17, David Hart <david@hartbit.com> wrote:

On 05 May 2016, at 12:30, Michael Peternell via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

it's not a secret that I'm not a big fan of the proposal. The third draft doesn't change this and it's unlikely that any future draft will, because for me, the problem are the continuation quotes, and for Brent it seems like they are a must-have-feature (correct me if I'm wrong.)

I agree with all you said. I’m fairly sure I would never vote for Brent’s proposal simply because of the existence of continuation quotes, no matter the amount of reasoning behind it. They are simply too unwieldy, cumbersome and unfriendly to modification.

I could see either your proposal, or your proposal without the HERE_DOCs but using Tyler’s/Scala’s .stripMargin. Do you think you could start a formal proposal?

it's not a secret that I'm not a big fan of the proposal. The third draft doesn't change this and it's unlikely that any future draft will, because for me, the problem are the continuation quotes, and for Brent it seems like they are a must-have-feature (correct me if I'm wrong.)

I agree with all you said. I’m fairly sure I would never vote for Brent’s proposal simply because of the existence of continuation quotes, no matter the amount of reasoning behind it. They are simply too unwieldy, cumbersome and unfriendly to modification.

I could see either your proposal, or your proposal without the HERE_DOCs but using Tyler’s/Scala’s .stripMargin. Do you think you could start a formal proposal?

Adapting the original proposal if you’re not a fan of continuation quotes..

It’s possible to have a multiline “””python””” multi-line string but tidily indented.
As suggested earlier in this thread the lexer can strip the margin on the basis of
the whitespace before the closing quote as per Perl6 (This could be a modifier “I”
but might as well be the default TBH.) Would this be the best of both worlds?

        assert( xml == i"""
            <?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>
            ""” )

Other modifiers can also be applied such as “no-escapes"

        assert( xml != ei"""<?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>
            """ )

I’d hope this would satisfy any need for <<HERE/<<‘HERE’ style constructs.

Or you could support both continuation and indented python style:
http://johnholdsworth.com/swift-LOCAL-2016-05-05-a-osx.tar.gz

John

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I’m of the opinion that either of these are reasonable solutions, and both offer different tradeoffs. I’m probably partial to the continuation quotes, because I don’t want to be guessing about what is going to end up being in my string and what won’t.

        assert( xml != ei"""<?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>
            ""” )

For example, is there a new line after </catalog>?
How would the indenting work if it were immediately followed by triple quotes: </catalog>”””
I would really like the first line to be lined up with the rest of the xml. Is that going to introduce a newline into the top of the string?

Could we just enforce that no characters on the lines of the triple quotes would be included in the string, very much like the heredoc syntax?

        assert( xml != ei"”” The text I’m typing here would cause a compiler error.
            <?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>
same here ""” )

Then it’s very clear what the whitespace stripping will do. But what about mixed tab vs whitespace? What is the behavior in that case?

Tyler

···

On May 5, 2016, at 5:08 PM, John Holdsworth via swift-evolution <swift-evolution@swift.org> wrote:

On 5 May 2016, at 14:17, David Hart <david@hartbit.com <mailto:david@hartbit.com>> wrote:

On 05 May 2016, at 12:30, Michael Peternell via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Then you could even, if you were so daring, put the string modifiers in the string as compiler directives.

        assert( xml !=
            “”” #escaped #marginStripped
            <?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>
            ""” )

Is this dirty? It sure feels dirty, but it also makes it so I can line up my triple quotes and finally achieve a zen state.

Tyler

···

On May 5, 2016, at 6:27 PM, Tyler Cloutier via swift-evolution <swift-evolution@swift.org> wrote:

On May 5, 2016, at 5:08 PM, John Holdsworth via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On 5 May 2016, at 14:17, David Hart <david@hartbit.com <mailto:david@hartbit.com>> wrote:

On 05 May 2016, at 12:30, Michael Peternell via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

it's not a secret that I'm not a big fan of the proposal. The third draft doesn't change this and it's unlikely that any future draft will, because for me, the problem are the continuation quotes, and for Brent it seems like they are a must-have-feature (correct me if I'm wrong.)

I agree with all you said. I’m fairly sure I would never vote for Brent’s proposal simply because of the existence of continuation quotes, no matter the amount of reasoning behind it. They are simply too unwieldy, cumbersome and unfriendly to modification.

I could see either your proposal, or your proposal without the HERE_DOCs but using Tyler’s/Scala’s .stripMargin. Do you think you could start a formal proposal?

Adapting the original proposal if you’re not a fan of continuation quotes..

It’s possible to have a multiline “””python””” multi-line string but tidily indented.
As suggested earlier in this thread the lexer can strip the margin on the basis of
the whitespace before the closing quote as per Perl6 (This could be a modifier “I”
but might as well be the default TBH.) Would this be the best of both worlds?

        assert( xml == i"""
            <?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>
            ""” )

Other modifiers can also be applied such as “no-escapes"

        assert( xml != ei"""<?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>
            """ )

I’d hope this would satisfy any need for <<HERE/<<‘HERE’ style constructs.

Or you could support both continuation and indented python style:
http://johnholdsworth.com/swift-LOCAL-2016-05-05-a-osx.tar.gz

John

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

I’m of the opinion that either of these are reasonable solutions, and both offer different tradeoffs. I’m probably partial to the continuation quotes, because I don’t want to be guessing about what is going to end up being in my string and what won’t.

        assert( xml != ei"""<?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>
            ""” )

For example, is there a new line after </catalog>?
How would the indenting work if it were immediately followed by triple quotes: </catalog>”””
I would really like the first line to be lined up with the rest of the xml. Is that going to introduce a newline into the top of the string?

Could we just enforce that no characters on the lines of the triple quotes would be included in the string, very much like the heredoc syntax?

        assert( xml != ei"”” The text I’m typing here would cause a compiler error.
            <?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>
same here ""” )

Then it’s very clear what the whitespace stripping will do. But what about mixed tab vs whitespace? What is the behavior in that case?

Tyler

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

it's not a secret that I'm not a big fan of the proposal. The third draft doesn't change this and it's unlikely that any future draft will, because for me, the problem are the continuation quotes, and for Brent it seems like they are a must-have-feature (correct me if I'm wrong.)

I agree with all you said. I’m fairly sure I would never vote for Brent’s proposal simply because of the existence of continuation quotes, no matter the amount of reasoning behind it. They are simply too unwieldy, cumbersome and unfriendly to modification.

I could see either your proposal, or your proposal without the HERE_DOCs but using Tyler’s/Scala’s .stripMargin. Do you think you could start a formal proposal?

Adapting the original proposal if you’re not a fan of continuation quotes..

It’s possible to have a multiline “””python””” multi-line string but tidily indented.
As suggested earlier in this thread the lexer can strip the margin on the basis of
the whitespace before the closing quote as per Perl6 (This could be a modifier “I”
but might as well be the default TBH.) Would this be the best of both worlds?

        assert( xml == i"""
            <?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>
            ""” )

Other modifiers can also be applied such as “no-escapes"

        assert( xml != ei"""<?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>
            """ )

I’d hope this would satisfy any need for <<HERE/<<‘HERE’ style constructs.

Or you could support both continuation and indented python style:
http://johnholdsworth.com/swift-LOCAL-2016-05-05-a-osx.tar.gz

John

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

I’m of the opinion that either of these are reasonable solutions, and both offer different tradeoffs. I’m probably partial to the continuation quotes, because I don’t want to be guessing about what is going to end up being in my string and what won’t.

        assert( xml != ei"""<?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>
            ""” )

For example, is there a new line after </catalog>?
How would the indenting work if it were immediately followed by triple quotes: </catalog>”””
I would really like the first line to be lined up with the rest of the xml. Is that going to introduce a newline into the top of the string?

Could we just enforce that no characters on the lines of the triple quotes would be included in the string, very much like the heredoc syntax?

        assert( xml != ei"”” The text I’m typing here would cause a compiler error.
            <?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>
same here ""” )

Then it’s very clear what the whitespace stripping will do. But what about mixed tab vs whitespace? What is the behavior in that case?

I’m jumping into this thread late and have only followed bits of it so I apologize if I’m repeating anything.

I really like the idea of having leading space stripped automatically without requiring the continuation quotes. I have done my share of leading space stripping in the past when working with heredocs. It’s not that big a deal but it would be better to have the language take care of it for us.

I like the idea of banning any characters on the same line as the triple quotes (not just omitting them but actually making it a syntax error to include them).

As far as mixed whitespace, I think the only sane thing to do would be to only allow leading tabs *or* spaces. Mixing tabs and spaces in the leading whitespace would be a syntax error. All lines in the string would need to use tabs or all lines use spaces, you could not have one line with tabs and another with spaces. This would keep the compiler out of the business of making any assumptions or guesses, would not be a problem often, and would be very easy to fix if it ever happens accidentally.

-Matthew

···

On May 5, 2016, at 8:27 PM, Tyler Cloutier via swift-evolution <swift-evolution@swift.org> wrote:

On May 5, 2016, at 5:08 PM, John Holdsworth via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On 5 May 2016, at 14:17, David Hart <david@hartbit.com <mailto:david@hartbit.com>> wrote:

On 05 May 2016, at 12:30, Michael Peternell via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Tyler

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

As far as mixed whitespace, I think the only sane thing to do would be to only allow leading tabs *or* spaces. Mixing tabs and spaces in the leading whitespace would be a syntax error. All lines in the string would need to use tabs or all lines use spaces, you could not have one line with tabs and another with spaces. This would keep the compiler out of the business of making any assumptions or guesses, would not be a problem often, and would be very easy to fix if it ever happens accidentally.

The sane thing to do would be to require every line be prefixed with *exactly* the same sequence of characters as the closing delimiter line. Anything else (except perhaps a completely blank line, to permit whitespace trimming) would be a syntax error.

But take a moment to consider the downsides before you leap to adopt this solution.

1. You have introduced tab-space confusion into the equation.

2. You have introduced trailing-newline confusion into the equation.

3. The #escaped and #marginStripped keywords are now specific to multiline strings; #escaped in particular will be attractive there for tasks like regexes. You will have to invent a different syntax for it there.

4. This form of `"""` is not useful for not having to escape `"` in a single-line string; you now have to invent a separate mechanism for that.

5. You can't necessarily look at a line and tell whether it's code or string. And—especially with the #escaped-style constructs—the delimiters don't necessarily "pop" visually; they're too small and easy to miss compared to the text they contain. In extremis, you actually have to look at the entire file from top to bottom, counting the `"""`s to figure out whether you're in a string or not. Granted, you *usually* can tell from context, but it's a far cry from what continuation quotes offer.

6. You are now forcing *any* string literal of more than one line to include two extra lines devoted wholly to the quoting syntax. In my Swift-generating example, that would change shorter snippets like this:

code += "
             " static var messages: [HTTPStatus: String] = [
             ""

Into things like this:

code += """
                 
                 static var messages: [HTTPStatus: String] = [
                            
             """

To my mind, the second syntax is actually *heavier*, despite not requiring every line be marked, because it takes two extra lines and additional punctuation.

7. You are also introducing visual ambiguity into the equation—in the above example, the left margin is now ambiguous to the eye (even if it's not ambiguous to the compiler). You could recover it by permitting non-whitespace prefix characters:

code += """
            >
            > static var messages: [HTTPStatus: String] = [
            >
            >"""

...but then we're back to annotating every line, *plus* we have the leading and trailing `"""` lines. Worst of both worlds.

8. In longer examples, you are dividing the expression in half in a way that makes it difficult to read. For instance, consider this code:

        socket.send(
            """ #escaped #marginStripped
            <?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>
            """.data(using: NSUTF8StringEncoding))

The effect—particularly with even larger literals than this—is not unlike pausing in the middle of reading an article to watch a movie. What were we talking about again?

This problem is neatly avoided by a heredoc syntax, which keeps the expression together and then collects the string below it:

        socket.send(""".data(using: NSUTF8StringEncoding))
            <?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>
            """

(I'm assuming there's no need for #escaped or #marginStripped; they're both enabled by default.)

* * *

Let's actually talk about heredocs. Leaving aside indentation (which can be applied to either feature) and the traditional token choices (which can be changed), I think these are the pros of heredocs compared to Python triple-quotes:

H1: Doesn't break up expressions, as discussed above.
H2: Literal content formatting is completely unaffected by code formatting, including the first and last lines.

Here are the pros of Python triple-quotes compared to heredocs:

P1: Simpler to explain: "like a string literal, but really big".
P2: Lighter syntactic weight, enough to make`"""` usable as a single-line syntax.
P3: Less trailing-newline confusion.

(There is one other difference: `"""` is simpler to parse, so we might be able to get it in Swift 3, whereas heredocs probably have to wait for Swift 4. But I don't think we should pick one feature over another merely so we can get it sooner. It's one thing if you plan to eventually introduce both features, as I plan to eventually have both continuation quotes and heredocs, to introduce each of them as soon as you can; it's another to actually choose one feature over another specifically to get something you can implement sooner.)

But the design you're discussing trades P2 and P3—and frankly, with the mandatory newlines, part of P1—away in an attempt to get H2. So we end up deciding between these two selling points:

* This triple-quotes design: Simpler to explain.
* Heredocs: Doesn't break up expressions.

Simplicity is good, but I really like the code reading benefits of heredocs. Your code is your code and your text is your text. The interface between them is a bit funky, but within their separate worlds, they're both pretty nice.

* * *

Either way, heredocs or multiline-only triple quotes could be tweaked to support indentation by using the indentation of the end delimiter. But as I explained above, I don't think that's a great idea for either triple quotes *or* heredocs—the edge of the indentation is not visually well defined enough.

That's why I came to the conclusion that trying to cram every multiline literal into one syntax is trying to cram too many peg shapes into one hole shape. Indentation should *only* be supported by a dedicated syntax which is also designed for the smallest multiline strings, where indentation support is most useful. A separate feature without indentation support should handle longer strings, where the length alone is so disruptive to the flow of your code that there's just no point even trying to indent them to match (and the break with normal indentation itself assists you in finding the end of the string).

And I think that the best choice for the first feature is continuation quotes, and for the second is heredocs. Triple-quote syntaxes—either Python's or this modification—are jacks of all trades, but masters of none.

···

--
Brent Royal-Gordon
Architechies

        assert( xml != ei"""<?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>
            """ )

The idea of auto-stripping whitespaces seemed nice initially, until I realized it's not at all clear where the stripped whitespaces end and the included whitespaces begin. It's already problematic for you own code (because even knowing your own intent doesn't completely overcome the lack of perspective this syntax offers), but imagine if it's someone else's. Will you be able to figure out what spacing is meant to be a part of the string and which is not? Quickly? Easily? Maybe, maybe not. It still won't be readily apparent, because there's no point of reference. You're potentially reduced to counting whitespaces to figure it out. Brent's proposal elegantly fixes this problem. You have a clear point of reference, there's no issue of spaces vs tabs, no trying to figure out exactly where the "true" whitespaces are beginning. Like was mentioned, it would probably have to be relative to the leading whitespaces on the closing delimiter line, but then there's no way to tell visually if those are spaces or tabs, or how many there are, AND you have to sort of mentally trace an invisible line upwards to "see" how the lines above relate. This would drive me crazy. With leading quotes, it's obvious which lines don't have included leading whitespaces, and the ones that do have a smaller relative distance to what is the "left alignment margin" (so to speak) indicated by the quotes.

This feels like we would be making it easier to make mistakes and harder to determine actual spacing just to eliminate some extra quotes. I think the proposal is the best balance of simplicity and practicality we're going to achieve for *short* multi line strings, which is what this proposal is tying to address. We can still introduce the """ or heredoc syntaxes for longer blocks of text in the future.

Cole

As far as mixed whitespace, I think the only sane thing to do would be to only allow leading tabs *or* spaces. Mixing tabs and spaces in the leading whitespace would be a syntax error. All lines in the string would need to use tabs or all lines use spaces, you could not have one line with tabs and another with spaces. This would keep the compiler out of the business of making any assumptions or guesses, would not be a problem often, and would be very easy to fix if it ever happens accidentally.

The sane thing to do would be to require every line be prefixed with *exactly* the same sequence of characters as the closing delimiter line. Anything else (except perhaps a completely blank line, to permit whitespace trimming) would be a syntax error.

Yes, this is the important implication of what I suggested.

But take a moment to consider the downsides before you leap to adopt this solution.

1. You have introduced tab-space confusion into the equation.

2. You have introduced trailing-newline confusion into the equation.

I don't think confusion is the right word. When tabs and spaces are mixed accidentally the compiler can offer a very clear error message. The problem is easy to understand and easy to fix.

The new line question is really just a matter of learning how the language works and then doing the right thing. Confusion only exists if you don't know the language, which can be said about pretty much any feature.

3. The #escaped and #marginStripped keywords are now specific to multiline strings; #escaped in particular will be attractive there for tasks like regexes. You will have to invent a different syntax for it there.

The syntax for those was not my suggestion.

4. This form of `"""` is not useful for not having to escape `"` in a single-line string; you now have to invent a separate mechanism for that.

I was only commenting on the leading space issue. If you prefer heredoc syntax that is fine with me.

5. You can't necessarily look at a line and tell whether it's code or string. And—especially with the #escaped-style constructs—the delimiters don't necessarily "pop" visually; they're too small and easy to miss compared to the text they contain. In extremis, you actually have to look at the entire file from top to bottom, counting the `"""`s to figure out whether you're in a string or not. Granted, you *usually* can tell from context, but it's a far cry from what continuation quotes offer.

This has never been a problem for me. I have used heredocs extensively in the past.

6. You are now forcing *any* string literal of more than one line to include two extra lines devoted wholly to the quoting syntax. In my Swift-generating example, that would change shorter snippets like this:

code += "
             " static var messages: [HTTPStatus: String] = [
             ""

Into things like this:

code += """
                 
                 static var messages: [HTTPStatus: String] = [
                            
             """

To my mind, the second syntax is actually *heavier*, despite not requiring every line be marked, because it takes two extra lines and additional punctuation.

Granted. But in my experience multi-line string literals are usually not so short. This has never bothered me in work with heredocs.

7. You are also introducing visual ambiguity into the equation—in the above example, the left margin is now ambiguous to the eye (even if it's not ambiguous to the compiler). You could recover it by permitting non-whitespace prefix characters:

code += """
            >
            > static var messages: [HTTPStatus: String] = [
            >
            >"""

...but then we're back to annotating every line, *plus* we have the leading and trailing `"""` lines. Worst of both worlds.

This is a reasonable point and one I hadn't thought of. I never had a problem with it when working with heredocs, but I can see where occasionally this would make a difference.

8. In longer examples, you are dividing the expression in half in a way that makes it difficult to read. For instance, consider this code:

        socket.send(
            """ #escaped #marginStripped
            <?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>
            """.data(using: NSUTF8StringEncoding))

The effect—particularly with even larger literals than this—is not unlike pausing in the middle of reading an article to watch a movie. What were we talking about again?

This problem is neatly avoided by a heredoc syntax, which keeps the expression together and then collects the string below it:

        socket.send(""".data(using: NSUTF8StringEncoding))
            <?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>
            """

(I'm assuming there's no need for #escaped or #marginStripped; they're both enabled by default.)

That's interesting. I haven't encountered syntax like that before. I think I like it but would have to consider it further.

Again, I was only commenting on the leading space issue, not triple quote vs heredoc.

* * *

Let's actually talk about heredocs. Leaving aside indentation (which can be applied to either feature) and the traditional token choices (which can be changed), I think these are the pros of heredocs compared to Python triple-quotes:

H1: Doesn't break up expressions, as discussed above.
H2: Literal content formatting is completely unaffected by code formatting, including the first and last lines.

Here are the pros of Python triple-quotes compared to heredocs:

P1: Simpler to explain: "like a string literal, but really big".
P2: Lighter syntactic weight, enough to make`"""` usable as a single-line syntax.
P3: Less trailing-newline confusion.

(There is one other difference: `"""` is simpler to parse, so we might be able to get it in Swift 3, whereas heredocs probably have to wait for Swift 4. But I don't think we should pick one feature over another merely so we can get it sooner. It's one thing if you plan to eventually introduce both features, as I plan to eventually have both continuation quotes and heredocs, to introduce each of them as soon as you can; it's another to actually choose one feature over another specifically to get something you can implement sooner.)

But the design you're discussing trades P2 and P3—and frankly, with the mandatory newlines, part of P1—away in an attempt to get H2. So we end up deciding between these two selling points:

* This triple-quotes design: Simpler to explain.
* Heredocs: Doesn't break up expressions.

Simplicity is good, but I really like the code reading benefits of heredocs. Your code is your code and your text is your text. The interface between them is a bit funky, but within their separate worlds, they're both pretty nice.

* * *

Either way, heredocs or multiline-only triple quotes could be tweaked to support indentation by using the indentation of the end delimiter. But as I explained above, I don't think that's a great idea for either triple quotes *or* heredocs—the edge of the indentation is not visually well defined enough.

How would you feel about making stripping a choice, like escapes, etc? I think building the option into the language is great. The reason is that almost every heredoc I ever wrote was stripped of leading space by code I had to write and call myself.

That's why I came to the conclusion that trying to cram every multiline literal into one syntax is trying to cram too many peg shapes into one hole shape. Indentation should *only* be supported by a dedicated syntax which is also designed for the smallest multiline strings, where indentation support is most useful. A separate feature without indentation support should handle longer strings, where the length alone is so disruptive to the flow of your code that there's just no point even trying to indent them to match (and the break with normal indentation itself assists you in finding the end of the string).

And I think that the best choice for the first feature is continuation quotes, and for the second is heredocs. Triple-quote syntaxes—either Python's or this modification—are jacks of all trades, but masters of none.

This is fine with me. Again, I was only commenting on the leading space issue. I don't mind continuation quotes if we think heredocs (or triple quotes) are also likely to be added. You make a good case for having both.

···

Sent from my iPad
On May 6, 2016, at 12:52 AM, Brent Royal-Gordon <brent@architechies.com> wrote:

--
Brent Royal-Gordon
Architechies

Inline

Regards
(From mobile)

it's not a secret that I'm not a big fan of the proposal. The third draft doesn't change this and it's unlikely that any future draft will, because for me, the problem are the continuation quotes, and for Brent it seems like they are a must-have-feature (correct me if I'm wrong.)

I agree with all you said. I’m fairly sure I would never vote for Brent’s proposal simply because of the existence of continuation quotes, no matter the amount of reasoning behind it. They are simply too unwieldy, cumbersome and unfriendly to modification.

I could see either your proposal, or your proposal without the HERE_DOCs but using Tyler’s/Scala’s .stripMargin. Do you think you could start a formal proposal?

Adapting the original proposal if you’re not a fan of continuation quotes..

It’s possible to have a multiline “””python””” multi-line string but tidily indented.
As suggested earlier in this thread the lexer can strip the margin on the basis of
the whitespace before the closing quote as per Perl6 (This could be a modifier “I”
but might as well be the default TBH.) Would this be the best of both worlds?

        assert( xml == i"""
            <?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>
            ""” )

Other modifiers can also be applied such as “no-escapes"

        assert( xml != ei"""<?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>
            """ )

I’d hope this would satisfy any need for <<HERE/<<‘HERE’ style constructs.

Or you could support both continuation and indented python style:
http://johnholdsworth.com/swift-LOCAL-2016-05-05-a-osx.tar.gz

John

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I’m of the opinion that either of these are reasonable solutions, and both offer different tradeoffs. I’m probably partial to the continuation quotes, because I don’t want to be guessing about what is going to end up being in my string and what won’t.

        assert( xml != ei"""<?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>
            ""” )

For example, is there a new line after </catalog>?
How would the indenting work if it were immediately followed by triple quotes: </catalog>”””
I would really like the first line to be lined up with the rest of the xml. Is that going to introduce a newline into the top of the string?

Could we just enforce that no characters on the lines of the triple quotes would be included in the string, very much like the heredoc syntax?

        assert( xml != ei"”” The text I’m typing here would cause a compiler error.
            <?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>
same here ""” )

Then it’s very clear what the whitespace stripping will do. But what about mixed tab vs whitespace? What is the behavior in that case?

I’m jumping into this thread late and have only followed bits of it so I apologize if I’m repeating anything.

I really like the idea of having leading space stripped automatically without requiring the continuation quotes. I have done my share of leading space stripping in the past when working with heredocs. It’s not that big a deal but it would be better to have the language take care of it for us.

I like the idea of banning any characters on the same line as the triple quotes (not just omitting them but actually making it a syntax error to include them).

As far as mixed whitespace, I think the only sane thing to do would be to only allow leading tabs *or* spaces. Mixing tabs and spaces in the leading whitespace would be a syntax error.

Upon first consideration, this does not strike me as realistic considering how we are talking about invisible character (requiring editor configuration to be materialisable) and how widely diverse the opinions which to use are, leading to all sorts of combinations in existing source code.

···

On May 6, 2016, at 4:13 AM, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:

On May 5, 2016, at 8:27 PM, Tyler Cloutier via swift-evolution <swift-evolution@swift.org> wrote:

On May 5, 2016, at 5:08 PM, John Holdsworth via swift-evolution <swift-evolution@swift.org> wrote:

On 5 May 2016, at 14:17, David Hart <david@hartbit.com> wrote:
On 05 May 2016, at 12:30, Michael Peternell via swift-evolution <swift-evolution@swift.org> wrote:

All lines in the string would need to use tabs or all lines use spaces, you could not have one line with tabs and another with spaces. This would keep the compiler out of the business of making any assumptions or guesses, would not be a problem often, and would be very easy to fix if it ever happens accidentally.

-Matthew

Tyler

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Hmm, I use syntax highlighting for this ;)

···

Am 06.05.2016 um 05:24 schrieb Ricardo Parada <rparada@mac.com>:

I think that is another one of the advantages of using the continuation quotes.

Sent from my iPhone

On May 5, 2016, at 4:51 PM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

I think it's nice that I can look at any line—out of context, random access—and see which parts are string literals.

As far as mixed whitespace, I think the only sane thing to do would be to only allow leading tabs *or* spaces. Mixing tabs and spaces in the leading whitespace would be a syntax error. All lines in the string would need to use tabs or all lines use spaces, you could not have one line with tabs and another with spaces. This would keep the compiler out of the business of making any assumptions or guesses, would not be a problem often, and would be very easy to fix if it ever happens accidentally.

The sane thing to do would be to require every line be prefixed with *exactly* the same sequence of characters as the closing delimiter line. Anything else (except perhaps a completely blank line, to permit whitespace trimming) would be a syntax error.

Yes, this I think would be the way to do it.

But take a moment to consider the downsides before you leap to adopt this solution.

1. You have introduced tab-space confusion into the equation.

Agreed, and that’s never fun since they are invisible. Confusing for people new to programming, I imagine.

2. You have introduced trailing-newline confusion into the equation.

Yes, you are absolutely right and I missed this one in my response. I assume you are referring to whether or not there is a new line after </catalog>, and if so how do you get rid of it without messing up the whitespace trimming.

Is this not also a problem for heredocs (if you want to use the closing delimiter to mark how much whitespace to trim)?

3. The #escaped and #marginStripped keywords are now specific to multiline strings; #escaped in particular will be attractive there for tasks like regexes. You will have to invent a different syntax for it there.

These were just straw man proposals, I don’t think that is what they should/would be. Just throwing the general idea out there.

4. This form of `"""` is not useful for not having to escape `"` in a single-line string; you now have to invent a separate mechanism for that.

True, unless you don’t mind taking up 3 lines to do it.

5. You can't necessarily look at a line and tell whether it's code or string. And—especially with the #escaped-style constructs—the delimiters don't necessarily "pop" visually; they're too small and easy to miss compared to the text they contain. In extremis, you actually have to look at the entire file from top to bottom, counting the `"""`s to figure out whether you're in a string or not. Granted, you *usually* can tell from context, but it's a far cry from what continuation quotes offer.

To be fair, syntax highlighting also helps with this, but it’s quite possible you are looking at the code in a context where it is not available.

I don’t see how the #compilerDirective modifiers make the delimiters any less visible, though

And, the same could be said for heredoc delimiters, I think. Although, that really depends on what the delimiters are.

6. You are now forcing *any* string literal of more than one line to include two extra lines devoted wholly to the quoting syntax. In my Swift-generating example, that would change shorter snippets like this:

code += "
             " static var messages: [HTTPStatus: String] = [
             ""

Into things like this:

code += """
                 
                 static var messages: [HTTPStatus: String] = [
                            
             """

To my mind, the second syntax is actually *heavier*, despite not requiring every line be marked, because it takes two extra lines and additional punctuation.

7. You are also introducing visual ambiguity into the equation—in the above example, the left margin is now ambiguous to the eye (even if it's not ambiguous to the compiler). You could recover it by permitting non-whitespace prefix characters:

code += """
            >
            > static var messages: [HTTPStatus: String] = [
            >
            >"""

...but then we're back to annotating every line, *plus* we have the leading and trailing `"""` lines. Worst of both worlds.

This is a good point. It takes up 5 lines, and you quite possibly will still have to go about counting spaces. It would be worse for the more whitespace you have.

8. In longer examples, you are dividing the expression in half in a way that makes it difficult to read. For instance, consider this code:

        socket.send(
            """ #escaped #marginStripped
            <?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>
            """.data(using: NSUTF8StringEncoding))

The effect—particularly with even larger literals than this—is not unlike pausing in the middle of reading an article to watch a movie. What were we talking about again?

This problem is neatly avoided by a heredoc syntax, which keeps the expression together and then collects the string below it:

        socket.send(""".data(using: NSUTF8StringEncoding))
            <?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>
            """

(I'm assuming there's no need for #escaped or #marginStripped; they're both enabled by default.)

I don’t really see the argument of pausing in the middle of the code. Isn’t that the mental model that most people have for string literals? If anything heredoc syntax would be more confusing.

Where would you put the modifiers then? I assume as modifying letters before the “””?

        socket.send(ei""".data(using: NSUTF8StringEncoding))

That would work and also be consistent with single line and continuation quote strings if this feature were added there.

Heredocs look like they would be harder to parse than the alternative syntax, no?

* * *

Let's actually talk about heredocs. Leaving aside indentation (which can be applied to either feature) and the traditional token choices (which can be changed), I think these are the pros of heredocs compared to Python triple-quotes:

H1: Doesn't break up expressions, as discussed above.
H2: Literal content formatting is completely unaffected by code formatting, including the first and last lines.

Here are the pros of Python triple-quotes compared to heredocs:

P1: Simpler to explain: "like a string literal, but really big".
P2: Lighter syntactic weight, enough to make`"""` usable as a single-line syntax.
P3: Less trailing-newline confusion.

(There is one other difference: `"""` is simpler to parse, so we might be able to get it in Swift 3, whereas heredocs probably have to wait for Swift 4. But I don't think we should pick one feature over another merely so we can get it sooner. It's one thing if you plan to eventually introduce both features, as I plan to eventually have both continuation quotes and heredocs, to introduce each of them as soon as you can; it's another to actually choose one feature over another specifically to get something you can implement sooner.)

But the design you're discussing trades P2 and P3—and frankly, with the mandatory newlines, part of P1—away in an attempt to get H2. So we end up deciding between these two selling points:

* This triple-quotes design: Simpler to explain.
* Heredocs: Doesn't break up expressions.

Simplicity is good, but I really like the code reading benefits of heredocs. Your code is your code and your text is your text. The interface between them is a bit funky, but within their separate worlds, they're both pretty nice.

I would support having both. I think they have sufficiently different use cases and tradeoffs to warrant two solutions. It is also nice that if implementing both were the way to go, continuation quotes could be added to Swift 3, and heredoc could come later if necessary.

···

On May 5, 2016, at 10:52 PM, Brent Royal-Gordon <brent@architechies.com> wrote:

* * *

Either way, heredocs or multiline-only triple quotes could be tweaked to support indentation by using the indentation of the end delimiter. But as I explained above, I don't think that's a great idea for either triple quotes *or* heredocs—the edge of the indentation is not visually well defined enough.

That's why I came to the conclusion that trying to cram every multiline literal into one syntax is trying to cram too many peg shapes into one hole shape. Indentation should *only* be supported by a dedicated syntax which is also designed for the smallest multiline strings, where indentation support is most useful. A separate feature without indentation support should handle longer strings, where the length alone is so disruptive to the flow of your code that there's just no point even trying to indent them to match (and the break with normal indentation itself assists you in finding the end of the string).

And I think that the best choice for the first feature is continuation quotes, and for the second is heredocs. Triple-quote syntaxes—either Python's or this modification—are jacks of all trades, but masters of none.

--
Brent Royal-Gordon
Architechies

As I (believe I) start to understand the parser, I somehow think that doing something like the following would
not violate (not take too much risk) the current Lexer/Parser
be somewhat reasonable to implement
address many of the reqs I read
leave some infrastructure in the Lexer/Parser to add more feature without needing to go back to square 0 next time

Any thoughts?!

#!/usr/bin/env xcrun swift

let s1 = "{\"key1\": \"stringValue\"}"

let s2 = _"{"key1": "stringValue"}"_

let s3 =
    /* this is the same template */
    _"{"key1": "stringValue"}"_

let s4 =
/* this is (almost) the same template */
_"
{
  "key1": "stringValue"
  , "key2": "stringValue"
}
"_

let s5 = @literal(json)
  /* this is exactly the same template as s4 */
  _"
  {
    "key1": "stringValue"
    , "key2": "stringValue"
  }
  "_

let s6 = @literal(json)
  /* this is exactly the same template as s5&s4 */
  _"
  >{
  > "key1": "stringValue"
  > , "key2": "stringValue"
  >}
  "_

Inline

Regards
(From mobile)

it's not a secret that I'm not a big fan of the proposal. The third draft doesn't change this and it's unlikely that any future draft will, because for me, the problem are the continuation quotes, and for Brent it seems like they are a must-have-feature (correct me if I'm wrong.)

I agree with all you said. I’m fairly sure I would never vote for Brent’s proposal simply because of the existence of continuation quotes, no matter the amount of reasoning behind it. They are simply too unwieldy, cumbersome and unfriendly to modification.

I could see either your proposal, or your proposal without the HERE_DOCs but using Tyler’s/Scala’s .stripMargin. Do you think you could start a formal proposal?

Adapting the original proposal if you’re not a fan of continuation quotes..

It’s possible to have a multiline “””python””” multi-line string but tidily indented.
As suggested earlier in this thread the lexer can strip the margin on the basis of
the whitespace before the closing quote as per Perl6 (This could be a modifier “I”
but might as well be the default TBH.) Would this be the best of both worlds?

        assert( xml == i"""
            <?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>
            ""” )

Other modifiers can also be applied such as “no-escapes"

        assert( xml != ei"""<?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>
            """ )

I’d hope this would satisfy any need for <<HERE/<<‘HERE’ style constructs.

Or you could support both continuation and indented python style:
http://johnholdsworth.com/swift-LOCAL-2016-05-05-a-osx.tar.gz

John

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I’m of the opinion that either of these are reasonable solutions, and both offer different tradeoffs. I’m probably partial to the continuation quotes, because I don’t want to be guessing about what is going to end up being in my string and what won’t.

        assert( xml != ei"""<?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>
            ""” )

For example, is there a new line after </catalog>?
How would the indenting work if it were immediately followed by triple quotes: </catalog>”””
I would really like the first line to be lined up with the rest of the xml. Is that going to introduce a newline into the top of the string?

Could we just enforce that no characters on the lines of the triple quotes would be included in the string, very much like the heredoc syntax?

        assert( xml != ei"”” The text I’m typing here would cause a compiler error.
            <?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>
same here ""” )

Then it’s very clear what the whitespace stripping will do. But what about mixed tab vs whitespace? What is the behavior in that case?

I’m jumping into this thread late and have only followed bits of it so I apologize if I’m repeating anything.

I really like the idea of having leading space stripped automatically without requiring the continuation quotes. I have done my share of leading space stripping in the past when working with heredocs. It’s not that big a deal but it would be better to have the language take care of it for us.

I like the idea of banning any characters on the same line as the triple quotes (not just omitting them but actually making it a syntax error to include them).

As far as mixed whitespace, I think the only sane thing to do would be to only allow leading tabs *or* spaces. Mixing tabs and spaces in the leading whitespace would be a syntax error.

Upon first consideration, this does not strike me as realistic considering how we are talking about invisible character (requiring editor configuration to be materialisable) and how widely diverse the opinions which to use are, leading to all sorts of combinations in existing source code.

However, most existing code will not mix tabs and spaces. It happens by accident occasionally, best practice is definitely to pick one and stick to it. Allowing either means most existing code will comply.

···

Sent from my iPad

On May 6, 2016, at 12:14 AM, L. Mihalkovic <laurent.mihalkovic@gmail.com> wrote:

On May 6, 2016, at 4:13 AM, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:

On May 5, 2016, at 8:27 PM, Tyler Cloutier via swift-evolution <swift-evolution@swift.org> wrote:

On May 5, 2016, at 5:08 PM, John Holdsworth via swift-evolution <swift-evolution@swift.org> wrote:

On 5 May 2016, at 14:17, David Hart <david@hartbit.com> wrote:
On 05 May 2016, at 12:30, Michael Peternell via swift-evolution <swift-evolution@swift.org> wrote:

All lines in the string would need to use tabs or all lines use spaces, you could not have one line with tabs and another with spaces. This would keep the compiler out of the business of making any assumptions or guesses, would not be a problem often, and would be very easy to fix if it ever happens accidentally.

-Matthew

Tyler

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

As I (believe I) start to understand the parser, I somehow think that doing something like the following would
not violate (not take too much risk) the current Lexer/Parser
be somewhat reasonable to implement
address many of the reqs I read
leave some infrastructure in the Lexer/Parser to add more feature without needing to go back to square 0 next time

Any thoughts?!

#!/usr/bin/env xcrun swift

let s1 = "{\"key1\": \"stringValue\"}"

let s2 = _"{"key1": "stringValue"}"_

let s3 =
    /* this is the same template */
    _"{"key1": "stringValue"}"_

let s4 =
/* this is (almost) the same template */
_"
{
  "key1": "stringValue"
  , "key2": "stringValue"
}
"_

let s5 = @literal(json)
  /* this is exactly the same template as s4 */
  _"
  {
    "key1": "stringValue"
    , "key2": "stringValue"
  }
  "_

sorry for the mistake, but I think the more appropriate way to say that should have been

let s5: @literal(json) String =
  /* this is exactly the same template as s4 */
  _"
  {
    "key1": "stringValue"
    , "key2": "stringValue"
  }
  "_

let s6 = @literal(json)
  /* this is exactly the same template as s5&s4 */
  _"
  >{
  > "key1": "stringValue"
  > , "key2": "stringValue"
  >}
  "_

same for s6 which should read

let s6: @literal(json) String = ...

I have not checked it the following would be enough

let s6: @literal(json) = ...

···

On May 6, 2016, at 7:13 PM, L Mihalkovic <laurent.mihalkovic@gmail.com> wrote:

As far as mixed whitespace, I think the only sane thing to do would be to only allow leading tabs *or* spaces. Mixing tabs and spaces in the leading whitespace would be a syntax error. All lines in the string would need to use tabs or all lines use spaces, you could not have one line with tabs and another with spaces. This would keep the compiler out of the business of making any assumptions or guesses, would not be a problem often, and would be very easy to fix if it ever happens accidentally.

The sane thing to do would be to require every line be prefixed with *exactly* the same sequence of characters as the closing delimiter line. Anything else (except perhaps a completely blank line, to permit whitespace trimming) would be a syntax error.

Yes, this I think would be the way to do it.

This is implemented this in today’s prototype toolchain (as a warning)
http://johnholdsworth.com/swift-LOCAL-2016-05-06-a-osx.tar.gz

Heredocs look like they would be harder to parse than the alternative syntax, no?

I’ve had a go at parsing HEREDOC (why does autocorrect always change this to HERETIC!)
It wasn’t as difficult as I’d expected once you comment out a few well meaning asserts in the
compiler. To keep lexing happy there are two variants <<“HEREDOC” and <<‘HEREDOC’.

        assert( (<<"XML" + <<"XML") == (xml + 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>
        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>
        XML

Its a credit to it's authors that Xcode and the remainder of the toolchain cope with this remarkably well
now that tokens arrive out of order. The weird colouring is an artefact I’ve not been able to resolve.

The changes are here: [Parse] Adjust Lexer to allow Multi-line string literals by johnno1962 · Pull Request #2275 · apple/swift · GitHub, and amount to an additional 60 lines of by no
means bullet proof code. The total changes for multi-line literals are now 10% of the Swift lib/Parse/Lexer.cpp.

Simplicity is good, but I really like the code reading benefits of heredocs. Your code is your code and your text is your text. The interface between them is a bit funky, but within their separate worlds, they're both pretty nice.

I would support having both. I think they have sufficiently different use cases and tradeoffs to warrant two solutions. It is also nice that if implementing both were the way to go, continuation quotes could be added to Swift 3, and heredoc could come later if necessary.

I agree, I think we should prepare a joint proposal with all three syntaxes to get consensus.

John

···

On 6 May 2016, at 20:09, Tyler Cloutier <cloutiertyler@aol.com> wrote:

On May 5, 2016, at 10:52 PM, Brent Royal-Gordon <brent@architechies.com <mailto:brent@architechies.com>> wrote:

Wanting to test the validity of some of the arguments I read on the main proposal, I worked on my own prototype. I think there is more freedom than seem to have been identified so far.

The syntax I am exploring is visible here: Swift multiline string literal prototype · GitHub

There are still a couple of things that do not work
serialization of the @string_literal attribute (I persist in thinking that a lot of good can come from being able to tag the contents of string literal)
skipping leading spaces on each lines, based on the indentation of the first line
removing some of the extra EOL (rule to be defined)

The following works:
comments
@string_literal(“xxxx”). At the moment the attribute value is a string_literal, maybe a identifier would be better, and maybe it should be @string_literal(type: “xxxx”), so that other properties can be added
the code is based on a string_multiline_literal tag to make these extension visible in the grammar (other prototypes rely on clever tricks in the Lexer)

let s0 = "s0"

let s1 = "{\"key1\": \"stringValue\"}"

let s2 = _"{"v2"}"_

let s3 =
    /* this is a template */
    _"{"key3": "stringValue"}"_

let s4 =
/* this is (almost) the same template */
_"
{
  "key4": "stringValue"
  , "key2": "stringValue"
}
"_

@string_literal("json") let s5 =
  /* this is exactly the same template as s5 */
  _"
  {
    "key5": "stringValue"
  }
  "_

@string_literal("json") let s6 =
  /* this is exactly the same template as s5 */
  _"
  >{
  > "key6": "stringValue"
  > , "key2": "stringValue"
  >}
  "_

···

On May 7, 2016, at 1:53 AM, John Holdsworth via swift-evolution <swift-evolution@swift.org> wrote:

I’ve had a go at parsing HEREDOC (why does autocorrect always change this to HERETIC!)
It wasn’t as difficult as I’d expected once you comment out a few well meaning asserts in the
compiler. To keep lexing happy there are two variants <<“HEREDOC” and <<‘HEREDOC’.

        assert( (<<"XML" + <<"XML") == (xml + 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>
        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>
        XML

Its a credit to it's authors that Xcode and the remainder of the toolchain cope with this remarkably well
now that tokens arrive out of order. The weird colouring is an artefact I’ve not been able to resolve.

The changes are here: [Parse] Adjust Lexer to allow Multi-line string literals by johnno1962 · Pull Request #2275 · apple/swift · GitHub, and amount to an additional 60 lines of by no
means bullet proof code. The total changes for multi-line literals are now 10% of the Swift lib/Parse/Lexer.cpp.

I’ve assembled a gist to summarise the main proposals of this thread.

At the moment there seem to be four proposals for multi-line strings:

1) Bent’s proposal for continuation quotes where if a conventional string
does not close, if the first non-whitespace character of the next line is “
(or perhaps |) the string is continued. This gives you precise control
over exactly what is in the string.

2) Tyler's original proposal involving strings that can contain newlines
delimited “””like this“”” as they are in python or, _”like this“_. This works
well in external editors and on github. Indentation is catered for by stripping
any whitespace before the closing quote from all lines in the string.

3) HEREDOC syntax <<“TAG” or <<‘TAG’ taken from languages like Perl
subject to the same indentation removal rules as “””strings””” above. This
has the advantage that the literal is clearly separated from your code.

4) Heck it all, why not all three syntaxes or some combination.

(There is a separate feature that all string literals can be prefixed by
e as in e”\w\d+” to turn of all escape processing for another day)

While the Swift Lexer could easily accommodate all these syntaxes there was
talk early on that Swift has more of a "one way, maximally elegant” ethos and
indeed I find it difficult imagine the Swift Book breathlessly describing all three
formats so I’m wondering if push came to shove which format people would chose?

My vote having undergone a "road to damascus" moment now we know it is
available sooner rather than later is.. HEREDOC! It’s well understood and
while at first it would seem to not be a good fit for Swift produces clear code.

Votes?

John

        // Multi-line string proposals
        // https://github.com/apple/swift/pull/2275

        // swift-evolution thread:
        // http://thread.gmane.org/gmane.comp.lang.swift.evolution/904/focus=15133

        // These examples should load in the prototype toolchain available here:
        // http://johnholdsworth.com/swift-LOCAL-2016-05-09-a-osx.tar.gz

        // The prototype currently parses three new forms of quoting
        // These new types are still string literals for the grammar.

        "the existing string literal format"
        _"a format that does not require you to escape " characters"_ // possibly redundant
        """a python-style syntax that will accept "'s and newlines in the string"""
        <<"HEREDOC"
        A full heredoc implementation (will always end in a newline)
        HEREDOC

        // These strings can be modified by prefixing the string by letters
        // There is currently only one, "e" to disable escape processing.
        // This is primarily used when specifying regular expressions.

        let str = "print(\"Hello, world!\\n\")"

        assert( e"print(\"Hello, world!\n\")" == str )
        assert( e_"print("Hello, world!\n")"_ == str )
        assert( e"""print("Hello, world!\n")""" == str )

        // Continuation quotes allow you to extend a standard string literal
        // over multiple lines. If a string does not close on a line and the
        // first non-whitespace character on the next line is " that line
        // will be a contination of the string including the newline character
        // (unless it is escaped). Interpolation and escapes process as before
        // unless the first segment of the string is modified by the "e" prefix.

        // The advantage of this format allows you to indent while giving
        // you precise control of exactly what is going into the literal.

        let author = "Gambardella, Matthew"

        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)

        // Perhaps, to avoid the zera crossing effect in text editors due to
        // the unbalanced quotes, the continuation character could be "|".
        // (newlines escaped with \ and blank lines are discarded.)

        assert( 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>
            >" )

        // _""_ quoted strings also suppport these behaviours but don't require
        // escaping of embedded " characters. Think of them as a being modifier
        // on conventional string literals. They support continuation quotes.

        assert( 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>\n"_ )

        // _"strings"_ could allow newlines and replace """strings""" discussed next

        assert( 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>
            "_ )

        // The triple quoted strings can contain newlines and, unless modified by "e"
        // will process interpolations and not require escaping of ". To allow indenting,
        // any whitespace characters that preceed the closing """ will be removed from
        // each line of the final literal. A warning is shown if lines do not contain
        // the exact same indentation characters. Any intial linefeed is also removed.

        // The advantage of this format is the """ introducer works well when syntax
        // highlighting in external editors and github as quotes are always balanced.

        assert( 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>
            """ )

        assert( xml != e"""<?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>
            """ )

        // heredoc syntax comes in two variants <<"TAG" and <<'TAG' (non-escaping, "e" prefix)
        // It applies the same indentation removal rules as does """. This change has wider
        // ramifications for the toolchain as compiler tokens are no longer in file order
        // and will take a while for a few problems to be ironed out. The more consistent
        // <<e"TAG" is a rather clumsy alternative to <<'TAG' for non-escaping strings.

        // HEREDOC's advantage is that the literal no longer interrupts the flow of your code.

        assert( (<<"XML" + <<"XML") == xml + 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>
        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>
        XML

        // For text you do not want to contain newlines, escape them using \

        print( <<"LOREM" )
        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt \
        ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco \
        laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in \
        voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat \
        non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\
        LOREM

These are my comments so far.

Regarding the use of _” and “_ : It works but I think the _ already has a meaning elsewhere and may bring just a little bit of confusion at first. But more than that, I’m not sure I like the way it looks aesthetically. I can’t quite explain it. It is one character shorter than the triple quote, i.e. “””. However, I wonder if other alternatives could work out better. For example, here’s a couple:

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>"@

and with optional continuation quote it would look like this:

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>"@

Regarding the HEREDOC notation, all I can say is that it looks heavier. It may be more flexible, but if @“”@ looks better (in my eyes) why would we want another alternative. I would prefer to keep the one that looks better and simpler.

···

On May 10, 2016, at 2:53 AM, John Holdsworth via swift-evolution <swift-evolution@swift.org> wrote:

I’ve assembled a gist to summarise the main proposals of this thread.

Multi-line String Zoo · GitHub

At the moment there seem to be four proposals for multi-line strings:

1) Bent’s proposal for continuation quotes where if a conventional string
does not close, if the first non-whitespace character of the next line is “
(or perhaps |) the string is continued. This gives you precise control
over exactly what is in the string.

2) Tyler's original proposal involving strings that can contain newlines
delimited “””like this“”” as they are in python or, _”like this“_. This works
well in external editors and on github. Indentation is catered for by stripping
any whitespace before the closing quote from all lines in the string.

3) HEREDOC syntax <<“TAG” or <<‘TAG’ taken from languages like Perl
subject to the same indentation removal rules as “””strings””” above. This
has the advantage that the literal is clearly separated from your code.

4) Heck it all, why not all three syntaxes or some combination.

(There is a separate feature that all string literals can be prefixed by
e as in e”\w\d+” to turn of all escape processing for another day)

While the Swift Lexer could easily accommodate all these syntaxes there was
talk early on that Swift has more of a "one way, maximally elegant” ethos and
indeed I find it difficult imagine the Swift Book breathlessly describing all three
formats so I’m wondering if push came to shove which format people would chose?

My vote having undergone a "road to damascus" moment now we know it is
available sooner rather than later is.. HEREDOC! It’s well understood and
while at first it would seem to not be a good fit for Swift produces clear code.

Votes?

John

        // Multi-line string proposals
        // [Parse] Adjust Lexer to allow Multi-line string literals by johnno1962 · Pull Request #2275 · apple/swift · GitHub

        // swift-evolution thread:
        // http://thread.gmane.org/gmane.comp.lang.swift.evolution/904/focus=15133

        // These examples should load in the prototype toolchain available here:
        // http://johnholdsworth.com/swift-LOCAL-2016-05-09-a-osx.tar.gz

        // The prototype currently parses three new forms of quoting
        // These new types are still string literals for the grammar.

        "the existing string literal format"
        _"a format that does not require you to escape " characters"_ // possibly redundant
        """a python-style syntax that will accept "'s and newlines in the string"""
        <<"HEREDOC"
        A full heredoc implementation (will always end in a newline)
        HEREDOC

        // These strings can be modified by prefixing the string by letters
        // There is currently only one, "e" to disable escape processing.
        // This is primarily used when specifying regular expressions.

        let str = "print(\"Hello, world!\\n\")"

        assert( e"print(\"Hello, world!\n\")" == str )
        assert( e_"print("Hello, world!\n")"_ == str )
        assert( e"""print("Hello, world!\n")""" == str )

        // Continuation quotes allow you to extend a standard string literal
        // over multiple lines. If a string does not close on a line and the
        // first non-whitespace character on the next line is " that line
        // will be a contination of the string including the newline character
        // (unless it is escaped). Interpolation and escapes process as before
        // unless the first segment of the string is modified by the "e" prefix.

        // The advantage of this format allows you to indent while giving
        // you precise control of exactly what is going into the literal.

        let author = "Gambardella, Matthew"

        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)

        // Perhaps, to avoid the zera crossing effect in text editors due to
        // the unbalanced quotes, the continuation character could be "|".
        // (newlines escaped with \ and blank lines are discarded.)

        assert( 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>
            >" )

        // _""_ quoted strings also suppport these behaviours but don't require
        // escaping of embedded " characters. Think of them as a being modifier
        // on conventional string literals. They support continuation quotes.

        assert( 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>\n"_ )

        // _"strings"_ could allow newlines and replace """strings""" discussed next

        assert( 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>
            "_ )

        // The triple quoted strings can contain newlines and, unless modified by "e"
        // will process interpolations and not require escaping of ". To allow indenting,
        // any whitespace characters that preceed the closing """ will be removed from
        // each line of the final literal. A warning is shown if lines do not contain
        // the exact same indentation characters. Any intial linefeed is also removed.

        // The advantage of this format is the """ introducer works well when syntax
        // highlighting in external editors and github as quotes are always balanced.

        assert( 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>
            """ )

        assert( xml != e"""<?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>
            """ )

        // heredoc syntax comes in two variants <<"TAG" and <<'TAG' (non-escaping, "e" prefix)
        // It applies the same indentation removal rules as does """. This change has wider
        // ramifications for the toolchain as compiler tokens are no longer in file order
        // and will take a while for a few problems to be ironed out. The more consistent
        // <<e"TAG" is a rather clumsy alternative to <<'TAG' for non-escaping strings.

        // HEREDOC's advantage is that the literal no longer interrupts the flow of your code.

        assert( (<<"XML" + <<"XML") == xml + 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>
        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>
        XML

        // For text you do not want to contain newlines, escape them using \

        print( <<"LOREM" )
        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt \
        ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco \
        laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in \
        voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat \
        non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\
        LOREM

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution