multi-line string literals

Just a thought: what about something more generalized & explicit, like a
MultilineLiteral type (a.k.a. StaticString), and a String initializer with
parameters for the options:

String.init(removeLeadingNewline: Bool = false, removeIndentation: Bool =
false, _ mulitilineLiteral: MultilineLiteral)

let str = """
   raw string; nothing changed
"""

let str2 = String(removeLeadingNewline: true, """
    leading newline is removed, but indentation remains
""")

let str3 = String(removeIndentation: true, """
    leading newline remains, but as much indentation as possible is removed
""")

(I'm not a fan of the trailing close-paren, but can't really think of a way
around it. Maybe an exception like trailing-closure syntax for
trailing-multiline-literals?)

Jacob

···

On Thu, Dec 10, 2015 at 10:38 PM, Jason Dusek via swift-evolution < swift-evolution@swift.org> wrote:

Yeah, I can't say I am totally committed to the fourth one.

On Thu, 10 Dec 2015 at 22:34 Travis Tilley <ttilley@gmail.com> wrote:

I had been operating on the assumption that a leading blank line would be
stripped if present, since the syntax in code would look much cleaner, but
a trailing line would not since it would likely be intentional. I guess
that's another detail that would need to be fleshed out if we decide to go
with triple quote syntax (which, at this point, isn't a given... chris
lattner brings up some very good points that might require more involved,
potentially heredoc-like, syntax to solve).

Your fourth rule, however, I don't agree with at all. It should be
obvious from where you place the final quotes whether or not the string
includes a trailing newline. Just like in ruby, I believe in and value the
principle of least surprize.

- Travis Tilley

On Fri, Dec 11, 2015 at 1:04 AM, Jason Dusek <jason.dusek@gmail.com> >> wrote:

On Thu, 10 Dec 2015 at 21:45, Travis Tilley via swift-evolution < >>> swift-evolution@swift.org> wrote:

The ruby <<- heredoc syntax, unlike the << heredoc syntax, will strip

indentation if necessary. Technically, it searches for the "least indented
line" in the whole string, and removes exactly that amount from each line.
So yes, the indentation problem -is- solved in ruby (though it might break
entirely if you have empty lines, since the least indented line has no
indentation).

To my mind, the rules should be:

   1. The indentation level is set from the least indented line that is
   not the first line and is not empty.
   2. A leading empty line is removed.
   3. The leading line, if there is any text in it, is not subject to
   de-indentation.

I genuinely believe these three rules taken together address all the
errors and infelicities to which triple quotes and HEREDOCs subject us.
Here are some examples:

text = """
    Some

  Features
    Are
    Discussed
"""# From (1): The indentation is taken from the third line below `text`, so it's 2.# From (2): First line is: "\n" so it is removed.# From (3): No effect.

text = """ Some

          Features
            Are
            Discussed
"""# From (1): The indentation is taken again from the line reading "Features". Here it is 10.# From (2): No effect.# From (3): The leading whitespace in ` Some` is preserved.

Do you all think these rules pass muster?

A fourth rule — one which seems advisable but also less necessary than
the others — is that a string constructed in this way always ends with a
newline. It is a rule that perhaps leads to surprises and inconsistencies.

Best Regards,

Jason

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

But I think str3 is what most of us want most of the time -- so why do we
have to pass options for it? Let the unusual cases have options.

···

On Thu, 10 Dec 2015 at 22:46 Jacob Bandes-Storch <jtbandes@gmail.com> wrote:

Just a thought: what about something more generalized & explicit, like a
MultilineLiteral type (a.k.a. StaticString), and a String initializer with
parameters for the options:

String.init(removeLeadingNewline: Bool = false, removeIndentation: Bool =
false, _ mulitilineLiteral: MultilineLiteral)

let str = """
   raw string; nothing changed
"""

let str2 = String(removeLeadingNewline: true, """
    leading newline is removed, but indentation remains
""")

let str3 = String(removeIndentation: true, """
    leading newline remains, but as much indentation as possible is removed
""")

(I'm not a fan of the trailing close-paren, but can't really think of a
way around it. Maybe an exception like trailing-closure syntax for
trailing-multiline-literals?)

Jacob

On Thu, Dec 10, 2015 at 10:38 PM, Jason Dusek via swift-evolution < > swift-evolution@swift.org> wrote:

Yeah, I can't say I am totally committed to the fourth one.

On Thu, 10 Dec 2015 at 22:34 Travis Tilley <ttilley@gmail.com> wrote:

I had been operating on the assumption that a leading blank line would
be stripped if present, since the syntax in code would look much cleaner,
but a trailing line would not since it would likely be intentional. I guess
that's another detail that would need to be fleshed out if we decide to go
with triple quote syntax (which, at this point, isn't a given... chris
lattner brings up some very good points that might require more involved,
potentially heredoc-like, syntax to solve).

Your fourth rule, however, I don't agree with at all. It should be
obvious from where you place the final quotes whether or not the string
includes a trailing newline. Just like in ruby, I believe in and value the
principle of least surprize.

- Travis Tilley

On Fri, Dec 11, 2015 at 1:04 AM, Jason Dusek <jason.dusek@gmail.com> >>> wrote:

On Thu, 10 Dec 2015 at 21:45, Travis Tilley via swift-evolution < >>>> swift-evolution@swift.org> wrote:

The ruby <<- heredoc syntax, unlike the << heredoc syntax, will strip

indentation if necessary. Technically, it searches for the "least indented
line" in the whole string, and removes exactly that amount from each line.
So yes, the indentation problem -is- solved in ruby (though it might break
entirely if you have empty lines, since the least indented line has no
indentation).

To my mind, the rules should be:

   1. The indentation level is set from the least indented line that
   is not the first line and is not empty.
   2. A leading empty line is removed.
   3. The leading line, if there is any text in it, is not subject to
   de-indentation.

I genuinely believe these three rules taken together address all the
errors and infelicities to which triple quotes and HEREDOCs subject us.
Here are some examples:

text = """
    Some

  Features
    Are
    Discussed
"""# From (1): The indentation is taken from the third line below `text`, so it's 2.# From (2): First line is: "\n" so it is removed.# From (3): No effect.

text = """ Some

          Features
            Are
            Discussed
"""# From (1): The indentation is taken again from the line reading "Features". Here it is 10.# From (2): No effect.# From (3): The leading whitespace in ` Some` is preserved.

Do you all think these rules pass muster?

A fourth rule — one which seems advisable but also less necessary than
the others — is that a string constructed in this way always ends with a
newline. It is a rule that perhaps leads to surprises and inconsistencies.

Best Regards,

Jason

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

I really don’t like the left-edge being in the zero column as it is completely inconsistent with the formatting of the rest of the language.

class CommandLineTool {
    func showHelp() {
        let text =
            """
            OVERVIEW: Swift compiler

            USAGE: swiftc [options] <inputs>

            MODES:
              -dump-ast Parse and type-check input file(s) and dump AST(s)
              -dump-parse Parse input file(s) and dump AST(s)
              -dump-type-refinement-contexts
                               Type-check input file(s) and dump type refinement contexts(s)
              -emit-assembly Emit assembly file(s) (-S)
              -emit-bc Emit LLVM BC file(s)

            ...

            """

         print(text)
     }
}

What you’re suggesting is that the above code should be this:

class CommandLineTool {
    func showHelp() {
        let text = """
OVERVIEW: Swift compiler

USAGE: swiftc [options] <inputs>

MODES:
  -dump-ast Parse and type-check input file(s) and dump AST(s)
  -dump-parse Parse input file(s) and dump AST(s)
  -dump-type-refinement-contexts
                   Type-check input file(s) and dump type refinement contexts(s)
  -emit-assembly Emit assembly file(s) (-S)
  -emit-bc Emit LLVM BC file(s)

...

"""

         print(text)
     }
}

That’s a compromise I’d rather not have to see in my code.

Another use case for this is for the content of test cases. Having many of these string literals within that file that are all left-edge aligned reduces the readability of the code.

-David

This example will break easily when tabs are used for indentation or when using refactoring tools to rename the variable:

let text = """
           This is ok.
    
           """

All that suggests is this form should be preferred:

let text =
    """
    This is ok.
    """

I write a lot of my text these days in markdown, so I’m pretty heavily influenced by the simplicity of that.

-David

···

On Dec 11, 2015, at 4:20 AM, Marc Knaup <marc@knaup.koeln> wrote:

What I suggest is to support both:

   - standalone triple-quote will use indentation as in your first example
   - triple-quote which is not stand-alone will use indentation as in your
   second example

···

On Fri, Dec 11, 2015 at 5:52 PM, David Owens II <david@owensd.io> wrote:

I really don’t like the left-edge being in the zero column as it is
completely inconsistent with the formatting of the rest of the language.

class CommandLineTool {
    func showHelp() {
        let text =
            """
            OVERVIEW: Swift compiler

            USAGE: swiftc [options] <inputs>

            MODES:
              -dump-ast Parse and type-check input file(s) and
dump AST(s)
              -dump-parse Parse input file(s) and dump AST(s)
              -dump-type-refinement-contexts
                               Type-check input file(s) and dump type
refinement contexts(s)
              -emit-assembly Emit assembly file(s) (-S)
              -emit-bc Emit LLVM BC file(s)

            ...

            """

         print(text)
     }
}

What you’re suggesting is that the above code should be this:

class CommandLineTool {
    func showHelp() {
        let text = """
OVERVIEW: Swift compiler

USAGE: swiftc [options] <inputs>

MODES:
  -dump-ast Parse and type-check input file(s) and dump AST(s)
  -dump-parse Parse input file(s) and dump AST(s)
  -dump-type-refinement-contexts
                   Type-check input file(s) and dump type refinement
contexts(s)
  -emit-assembly Emit assembly file(s) (-S)
  -emit-bc Emit LLVM BC file(s)

...

"""

         print(text)
     }
}

That’s a compromise I’d rather not have to see in my code.

Another use case for this is for the content of test cases. Having many of
these string literals within that file that are all left-edge aligned
reduces the readability of the code.

-David

On Dec 11, 2015, at 4:20 AM, Marc Knaup <marc@knaup.koeln> wrote:

This example will break easily when tabs are used for indentation or when
using refactoring tools to rename the variable:

let text = """
           This is ok.

           """

All that suggests is this form should be preferred:

let text =

    """
    This is ok.
    """

I write a lot of my text these days in markdown, so I’m pretty heavily
influenced by the simplicity of that.

-David

Also the concern about

let x = “foo

would not be a problem with this proposal since only the currently line plus the new line character would be considered part of the String. The weird thing here is that this would be valid syntax and x would be “foo\n”. Which is not so good.

Tyler

···

On Dec 14, 2015, at 1:50 PM, Tyler Cloutier via swift-evolution <swift-evolution@swift.org> wrote:

What about the following proposal, I’m afraid I don’t know if it’s possible to implement, but it really represents everything that I would like to see in a multiline String solution because it has no special syntax and the results are extremely straight forward and non-magical.

let x =
"This is a proposal for a multiline literal String in Swift. This syntax solves a number of problems that
"are common in other language's implementations of multiline Strings. This syntax is meant to be a
"a generalization of regular Swift literal Strings, whereby a String is considered to begin with an open quote
"and continue indefinitely until and including the end of the line (newline character),
"or the String is closed with an ending quote.
"
"Firstly, indentation is now very clear and explicit. It is easy to see what the resulting string will be.
" This is one level of indentation.
" This is two levels.
"
"Secondly, there is no need for newline character processesing since it is well defined what newline behavior
"should be.
"
"If a newline should be present in the code, but not in the resulting String it can be escaped with '\\' <smb://'> \
" like so.
"
"Alternatively, perhaps that behavior could be left out and still accomplished by appending Strings in the
" normal way with + or implicitly concatonated by the complier. Like so:
" This is a long single line literal String. This is a long single line literal String. This is a long single"
"line literal String."
"
"Thirdly, the indent level of these strings is decoupled from the indent level of the code, since there is a
        "well defined starting point for the String on each line.
    " Thus you can indent the code and the string independently.
"
"Lastly, I don't actually know if this is even possible to implement. I don't know if these creates ambiguities
"for the compiler, but it doesn't seem like it does at first glance.

This would require that adjacent Strings are automatically appended to each other by the compiler, (e.g. let x = “blah” “blah”, would be valid and x would equal “blahblah”. I don’t know how others would feel about something like this, but I’ve always wanted this behavior in multiline Strings. Perhaps I’ve forgotten some edge cases?

Tyler

On Dec 14, 2015, at 12:47 PM, Chris Lattner via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Dec 14, 2015, at 12:35 PM, Chris Lattner via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Dec 10, 2015, at 11:07 PM, Travis Tilley <ttilley@gmail.com <mailto:ttilley@gmail.com>> wrote:

Chris - due to the complexity involved, would it make sense to have multiple proposals? One syntax need not fulfill the needs of every use case.

I’m not sure how to interpret this question. Are you asking whether a proposal should start out simple, then have new things piled on top of it? Or are you suggesting it would be better to have multiple new language features solving different problems?

In this case, my personal preference is to have a really well thought out long term vision for what we are doing in this space, and then subset the implementation to start with the simple pieces. This avoids painting ourselves into a corner. Further, I really hope we can avoid adding N new string literal syntaxes. I see the existing one as the “simple” case, and the multiline case as the “advanced” case which can have knobs put on it for other advanced uses.

Catching up with the rest of this thread, here’s what I’d suggest:

- Please don’t extend simple “foo” strings to multiple lines.
- The ``` syntax is actually pretty interesting, I think that exploring it makes sense. “”” doesn’t seem problematic to me though.
- Please consider ways that the string can have extensible options applied to it. I haven’t thought much about this space, but the "String literal suffixes for defining types” has some interesting ideas (though using prefixes instead of suffixes seems appealing as was pointed out in some email).
- I completely agree with Brent’s observation that we shouldn’t optimize for multi-line literals embedded into the middle of some other large expression.

The “configuration” aspect of this feature has come up several times. It seems clear that the multi line literal has some obvious strong defaults: leading whitespace should be stripped, and escapes should be processed (including interpolation). That said, being able to disable these independent of each other is important, and there are lots of other behaviors that can be considered as well. I consider it a good thing for these behaviors to be explicit in the code.

As a strawman proposal (i.e. don’t take it seriously) to illustrate what I mean, you could use attributes for this, e.g. something like:

let foo = @disable_escape_processing ```
blah
blah
blah```

-Chris

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto: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

let x =
"This is a proposal for a multiline literal String in Swift. This syntax solves a number of problems that
"are common in other language's implementations of multiline Strings. This syntax is meant to be a
"a generalization of regular Swift literal Strings, whereby a String is considered to begin with an open quote
"and continue indefinitely until and including the end of the line (newline character),
"or the String is closed with an ending quote.

Damn, why didn’t I think of that? It’s something like my email-style syntax, but based on regular English punctuation conventions instead of Internet ones. (I assume, incidentally, that there’s meant to be a closing quote on the last line, and it would be a syntax error if there weren’t.)

You would want a “toggle line quoting” command in your editor, the same way many editors have a “toggle commenting” commandz. In Xcode, the natural keystroke would be Cmd-‘ or Cmd-", but that’s currently used for Jump to Next Issue/Jump to Previous Issue. If this feature is added, hopefully the Xcode guys see how much this needs that mapping.

···

--
Brent Royal-Gordon
Architechies

I like the idea of simple line prefixes, as often my reason for wanting a multi-line string literal is to express a formatted ‘screen’ of text (such as a command line help output).

Perhaps we can use an initial character other than double-quote to indicate a multi-line string in order to improve any ambiguity with the compiler? I think single quote is even available.

However, I think multi-line strings make the ability to disable escaping/interpolation more important, as there is a higher chance of a block of text just copy/pasted into place.

This does create issues for statement completion on the previous line, for instance you would likely need to do

  return “”+
  “Hello, World

-DW

···

On Dec 14, 2015, at 2:50 PM, Tyler Cloutier via swift-evolution <swift-evolution@swift.org> wrote:

What about the following proposal, I’m afraid I don’t know if it’s possible to implement, but it really represents everything that I would like to see in a multiline String solution because it has no special syntax and the results are extremely straight forward and non-magical.

let x =
"This is a proposal for a multiline literal String in Swift. This syntax solves a number of problems that
"are common in other language's implementations of multiline Strings. This syntax is meant to be a
"a generalization of regular Swift literal Strings, whereby a String is considered to begin with an open quote
"and continue indefinitely until and including the end of the line (newline character),
"or the String is closed with an ending quote.
"
"Firstly, indentation is now very clear and explicit. It is easy to see what the resulting string will be.
" This is one level of indentation.
" This is two levels.
"
"Secondly, there is no need for newline character processesing since it is well defined what newline behavior
"should be.
"
"If a newline should be present in the code, but not in the resulting String it can be escaped with '\\' <smb://'> \
" like so.
"
"Alternatively, perhaps that behavior could be left out and still accomplished by appending Strings in the
" normal way with + or implicitly concatonated by the complier. Like so:
" This is a long single line literal String. This is a long single line literal String. This is a long single"
"line literal String."
"
"Thirdly, the indent level of these strings is decoupled from the indent level of the code, since there is a
        "well defined starting point for the String on each line.
    " Thus you can indent the code and the string independently.
"
"Lastly, I don't actually know if this is even possible to implement. I don't know if these creates ambiguities
"for the compiler, but it doesn't seem like it does at first glance.

This would require that adjacent Strings are automatically appended to each other by the compiler, (e.g. let x = “blah” “blah”, would be valid and x would equal “blahblah”. I don’t know how others would feel about something like this, but I’ve always wanted this behavior in multiline Strings. Perhaps I’ve forgotten some edge cases?

Tyler

On Dec 14, 2015, at 12:47 PM, Chris Lattner via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Dec 14, 2015, at 12:35 PM, Chris Lattner via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Dec 10, 2015, at 11:07 PM, Travis Tilley <ttilley@gmail.com <mailto:ttilley@gmail.com>> wrote:

Chris - due to the complexity involved, would it make sense to have multiple proposals? One syntax need not fulfill the needs of every use case.

I’m not sure how to interpret this question. Are you asking whether a proposal should start out simple, then have new things piled on top of it? Or are you suggesting it would be better to have multiple new language features solving different problems?

In this case, my personal preference is to have a really well thought out long term vision for what we are doing in this space, and then subset the implementation to start with the simple pieces. This avoids painting ourselves into a corner. Further, I really hope we can avoid adding N new string literal syntaxes. I see the existing one as the “simple” case, and the multiline case as the “advanced” case which can have knobs put on it for other advanced uses.

Catching up with the rest of this thread, here’s what I’d suggest:

- Please don’t extend simple “foo” strings to multiple lines.
- The ``` syntax is actually pretty interesting, I think that exploring it makes sense. “”” doesn’t seem problematic to me though.
- Please consider ways that the string can have extensible options applied to it. I haven’t thought much about this space, but the "String literal suffixes for defining types” has some interesting ideas (though using prefixes instead of suffixes seems appealing as was pointed out in some email).
- I completely agree with Brent’s observation that we shouldn’t optimize for multi-line literals embedded into the middle of some other large expression.

The “configuration” aspect of this feature has come up several times. It seems clear that the multi line literal has some obvious strong defaults: leading whitespace should be stripped, and escapes should be processed (including interpolation). That said, being able to disable these independent of each other is important, and there are lots of other behaviors that can be considered as well. I consider it a good thing for these behaviors to be explicit in the code.

As a strawman proposal (i.e. don’t take it seriously) to illustrate what I mean, you could use attributes for this, e.g. something like:

let foo = @disable_escape_processing ```
blah
blah
blah```

-Chris

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

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

2) using ' means that the string contents are unescaped/raw

I wonder if that's too subtle. Like Chris, I would prefer advanced knobs to be (i) more distinctive than ' vs ", and possibly (ii) only attached to the advanced string type.

5) the first line, if it contains only a newline, is removed entirely (this lets you just start your text on the next line)

I'm wibbly wobbly about the last line containing only a newline. I'm not sure whether to err on the side of caution and assume it's intentional, or remove it as well. At the moment I'm leaning toward assuming it's intentional.

I'd say trim 'em all, because right now I'm using ` literals in Go tests and trimming them like crazy, and I don't remember ever using a heredoc without passing it through trim.

4) indentation erasure is from the least indented line (from start of line, not start of quote)

I'm also not entirely sure what to do in the case of mixed indentation. I could absolutely see the leading indentation being tabs (with the editor displaying them as equivalent to 4 spaces), but the slight indentation of one to three characters being spaces.

Ideally, a tab character would be a syntax error in Swift, period. Eat it, Go.

More realistically, you want to issue a syntax error if all non-empty lines don't share a common whitespace prefix that entirely covers at least one of the whitespace prefixes.

Here is the SQL example for reference to show what I mean:

To be fair, SQL doesn't care about the leading whitespace, so it would be quite fine with any sort of trimming we implement.

A.

Also copying and pasting is not so fun, unless the beginning quotes were automatically added by the IDE.

Tyler

···

On Dec 14, 2015, at 1:53 PM, Tyler Cloutier <cloutiertyler@aol.com> wrote:

Also the concern about

let x = “foo

would not be a problem with this proposal since only the currently line plus the new line character would be considered part of the String. The weird thing here is that this would be valid syntax and x would be “foo\n”. Which is not so good.

Tyler

On Dec 14, 2015, at 1:50 PM, Tyler Cloutier via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

What about the following proposal, I’m afraid I don’t know if it’s possible to implement, but it really represents everything that I would like to see in a multiline String solution because it has no special syntax and the results are extremely straight forward and non-magical.

let x =
"This is a proposal for a multiline literal String in Swift. This syntax solves a number of problems that
"are common in other language's implementations of multiline Strings. This syntax is meant to be a
"a generalization of regular Swift literal Strings, whereby a String is considered to begin with an open quote
"and continue indefinitely until and including the end of the line (newline character),
"or the String is closed with an ending quote.
"
"Firstly, indentation is now very clear and explicit. It is easy to see what the resulting string will be.
" This is one level of indentation.
" This is two levels.
"
"Secondly, there is no need for newline character processesing since it is well defined what newline behavior
"should be.
"
"If a newline should be present in the code, but not in the resulting String it can be escaped with '\\' <smb://'> \
" like so.
"
"Alternatively, perhaps that behavior could be left out and still accomplished by appending Strings in the
" normal way with + or implicitly concatonated by the complier. Like so:
" This is a long single line literal String. This is a long single line literal String. This is a long single"
"line literal String."
"
"Thirdly, the indent level of these strings is decoupled from the indent level of the code, since there is a
        "well defined starting point for the String on each line.
    " Thus you can indent the code and the string independently.
"
"Lastly, I don't actually know if this is even possible to implement. I don't know if these creates ambiguities
"for the compiler, but it doesn't seem like it does at first glance.

This would require that adjacent Strings are automatically appended to each other by the compiler, (e.g. let x = “blah” “blah”, would be valid and x would equal “blahblah”. I don’t know how others would feel about something like this, but I’ve always wanted this behavior in multiline Strings. Perhaps I’ve forgotten some edge cases?

Tyler

On Dec 14, 2015, at 12:47 PM, Chris Lattner via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Dec 14, 2015, at 12:35 PM, Chris Lattner via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Dec 10, 2015, at 11:07 PM, Travis Tilley <ttilley@gmail.com <mailto:ttilley@gmail.com>> wrote:

Chris - due to the complexity involved, would it make sense to have multiple proposals? One syntax need not fulfill the needs of every use case.

I’m not sure how to interpret this question. Are you asking whether a proposal should start out simple, then have new things piled on top of it? Or are you suggesting it would be better to have multiple new language features solving different problems?

In this case, my personal preference is to have a really well thought out long term vision for what we are doing in this space, and then subset the implementation to start with the simple pieces. This avoids painting ourselves into a corner. Further, I really hope we can avoid adding N new string literal syntaxes. I see the existing one as the “simple” case, and the multiline case as the “advanced” case which can have knobs put on it for other advanced uses.

Catching up with the rest of this thread, here’s what I’d suggest:

- Please don’t extend simple “foo” strings to multiple lines.
- The ``` syntax is actually pretty interesting, I think that exploring it makes sense. “”” doesn’t seem problematic to me though.
- Please consider ways that the string can have extensible options applied to it. I haven’t thought much about this space, but the "String literal suffixes for defining types” has some interesting ideas (though using prefixes instead of suffixes seems appealing as was pointed out in some email).
- I completely agree with Brent’s observation that we shouldn’t optimize for multi-line literals embedded into the middle of some other large expression.

The “configuration” aspect of this feature has come up several times. It seems clear that the multi line literal has some obvious strong defaults: leading whitespace should be stripped, and escapes should be processed (including interpolation). That said, being able to disable these independent of each other is important, and there are lots of other behaviors that can be considered as well. I consider it a good thing for these behaviors to be explicit in the code.

As a strawman proposal (i.e. don’t take it seriously) to illustrate what I mean, you could use attributes for this, e.g. something like:

let foo = @disable_escape_processing ```
blah
blah
blah```

-Chris

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

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

Yes, you are right, Brent, there should be a closing quote on the last line otherwise it would be a syntax error. That’s a much better idea! That would also fix the

let x = “foo

being valid syntax problem.

Tyler

···

On Dec 14, 2015, at 2:10 PM, Brent Royal-Gordon <brent@architechies.com> wrote:

let x =
"This is a proposal for a multiline literal String in Swift. This syntax solves a number of problems that
"are common in other language's implementations of multiline Strings. This syntax is meant to be a
"a generalization of regular Swift literal Strings, whereby a String is considered to begin with an open quote
"and continue indefinitely until and including the end of the line (newline character),
"or the String is closed with an ending quote.

Damn, why didn’t I think of that? It’s something like my email-style syntax, but based on regular English punctuation conventions instead of Internet ones. (I assume, incidentally, that there’s meant to be a closing quote on the last line, and it would be a syntax error if there weren’t.)

You would want a “toggle line quoting” command in your editor, the same way many editors have a “toggle commenting” commandz. In Xcode, the natural keystroke would be Cmd-‘ or Cmd-", but that’s currently used for Jump to Next Issue/Jump to Previous Issue. If this feature is added, hopefully the Xcode guys see how much this needs that mapping.

--
Brent Royal-Gordon
Architechies

2) using ' means that the string contents are unescaped/raw

I wonder if that's too subtle. Like Chris, I would prefer advanced knobs to be (i) more distinctive than ' vs ", and possibly (ii) only attached to the advanced string type.

Anyone coming from ruby would feel right at home, but i'm having trouble finding precedent in any other language for that behavior. You may be right.

Ruby copied this feature from Perl, which copied it from Unix shells. (I will not attempt to untangle the history of Unix shells in order to figure out which one invented this.) I’m not necessarily saying it’s a good idea, but programming systems have been doing this for at least thirty years, and likely forty or more. There’s ample precedent.

···

--
Brent Royal-Gordon
Architechies

2) using ' means that the string contents are unescaped/raw

I wonder if that's too subtle. Like Chris, I would prefer advanced knobs
to be (i) more distinctive than ' vs ", and possibly (ii) only attached to
the advanced string type.

Anyone coming from ruby would feel right at home, but i'm having trouble
finding precedent in any other language for that behavior. You may be right.

Ideally, a tab character would be a syntax error in Swift, period. Eat it,

Go.

More realistically, you want to issue a syntax error if all non-empty
lines don't share a common whitespace prefix that entirely covers at least
one of the whitespace prefixes.

​I don't think it's the language's job to enforce preferences here,
especially given that holy wars have been fought over indentation (as well
as things much less important). Having 3 lines all started by the same
number of tabs, but with two having spaces as well for sub-tab-length
indentation, should never be an error.

​-Travis Tilley

···

On Mon, Dec 14, 2015 at 5:14 PM, Andrey Tarantsov <andrey@tarantsov.com> wrote:

​Then again, similar behavior in python (prefixing a string with r to
qualify it as a 'raw' string) would be completely unintuitive because
backslash behavior is... weird. For example, r"\" is not a valid string.
You can't have a string that's just a backslash just in case it can be
processed as an escape even though raw strings aren't supposed to process
escapes. Some other things are weird... So having blanket "yes, it's really
raw" behavior -might- be unintuitive for people coming from python.

BUT... And this is a massive but... It -would- tie into the discussion that
currently exists for typed literals (something i'm currently mostly
ignorant of and would love to hear more about). Especially since it would
put the qualifier in front of the literal.

​-Travis Tilley

···

On Mon, Dec 14, 2015 at 5:27 PM, Travis Tilley <ttilley@gmail.com> wrote:

On Mon, Dec 14, 2015 at 5:14 PM, Andrey Tarantsov <andrey@tarantsov.com> > wrote:

2) using ' means that the string contents are unescaped/raw

I wonder if that's too subtle. Like Chris, I would prefer advanced knobs
to be (i) more distinctive than ' vs ", and possibly (ii) only attached to
the advanced string type.

Anyone coming from ruby would feel right at home, but i'm having trouble
finding precedent in any other language for that behavior. You may be right.

...you know, I've been considering Bourne such a core part of the *nix
experience for so long that I didn't even think of it as a programming
language. It didn't even exist as a consideration in my mind. *shakes his
head*

Thank you.

-Travis Tilley

···

On Mon, Dec 14, 2015 at 5:38 PM, Brent Royal-Gordon <brent@architechies.com> wrote:

>> 2) using ' means that the string contents are unescaped/raw
>
> I wonder if that's too subtle. Like Chris, I would prefer advanced knobs
to be (i) more distinctive than ' vs ", and possibly (ii) only attached to
the advanced string type.
>
> Anyone coming from ruby would feel right at home, but i'm having trouble
finding precedent in any other language for that behavior. You may be right.

Ruby copied this feature from Perl, which copied it from Unix shells. (I
will not attempt to untangle the history of Unix shells in order to figure
out which one invented this.) I’m not necessarily saying it’s a good idea,
but programming systems have been doing this for at least thirty years, and
likely forty or more. There’s ample precedent.

--
Brent Royal-Gordon
Architechies

I don't think it's the language's job to enforce preferences here, especially given that holy wars have been fought over indentation (as well as things much less important)

Actually, as Go shows (and perhaps the Ada's style checking mode a few decades before it), it's precisely the language's job, for exactly that reason. Any bikeshedding that can be avoided, should be. (I'm also enjoying the Standard JavaScript movement of late.)

Having 3 lines all started by the same number of tabs, but with two having spaces as well for sub-tab-length indentation, should never be an error.

But to be clear, that wouldn't be an error in my proposed rule, which is, again (I wish I knew how to say this in a simpler way):

you want to issue a syntax error if all non-empty lines don't share a common whitespace prefix that entirely covers at least one of the whitespace prefixes.

A.

BUT... And this is a massive but... It -would- tie into the discussion that currently exists for typed literals (something i'm currently mostly ignorant of and would love to hear more about). Especially since it would put the qualifier in front of the literal.

I'm basically expecting a prefix like r'c:\program files\swift\swift.exe' to be the best solution. :-)

And yes, would be nice to have other and user-defined prefixes, although I would say that it should wait until a proper macro support. A user-definable prefix *is* a simple form of a macro, after all.

A.

Yes, you are right, Brent, there should be a closing quote on the last line otherwise it would be a syntax error. That’s a much better idea! That would also fix the

let x = “foo

being valid syntax problem.

So, based on this idea, here’s what I propose. We have two orthogonal features:

ADJUSTABLE DELIMITERS:

Any odd number of “ characters can be used to delimit a quoted string. That means you can start and end one with “, “””, “””””, “””””””, etc. (In practice, more than three would probably only be used when generating code which itself includes multiline strings.) This only affects how many quotes in a row you have to backslash inside the string; it does not imply the string is multiline.

MULTILINE STRINGS:

If a quoted string does not terminate by the end of the line, Swift examines the next line of code. If that line starts with zero or more whitespace characters, followed by the same string delimiter used to open the string on the previous line, then the string literal includes the newline character at the end of the previous line and then continues on the next line.

If the next line has anything else before the delimiter—including a string delimiter which is not long enough, a comment, or a newline—Swift concludes that the string does not continue onto this line and emits an unterminated string error on the previous line. Thus, an unterminated multi-line string is always detectable in and of itself.

Swift does not do any other special processing of the string, like removing indentation (all indentation should be before the string delimiter on that line) or trimming newlines at the beginning or end. All escapes function as normal; any modification of escaping is reserved for other mechanisms outside the scope of this thread.

···

--
Brent Royal-Gordon
Architechies

StringLiteralConvertable is more than sufficient for bending string
literals to your will. There's already several libraries that make use of
that, plus custom operators, to implement regular expression literals. Lets
not get too carried away and stick to defining the syntax for the literal
itself... I'm pretty sure the community will amaze us with what happens
afterwards and none of it will require macros.

​-Travis Tilley​

···

On Mon, Dec 14, 2015 at 5:51 PM, Andrey Tarantsov <andrey@tarantsov.com> wrote:

BUT... And this is a massive but... It -would- tie into the discussion
that currently exists for typed literals (something i'm currently mostly
ignorant of and would love to hear more about). Especially since it would
put the qualifier in front of the literal.

I'm basically expecting a prefix like r'c:\program files\swift\swift.exe'
to be the best solution. :-)

And yes, would be nice to have other and user-defined prefixes, although I
would say that it should wait until a proper macro support. A
user-definable prefix *is* a simple form of a macro, after all.

A.

Yes, you are right, Brent, there should be a closing quote on the last line otherwise it would be a syntax error. That’s a much better idea! That would also fix the

let x = “foo

being valid syntax problem.

Guys, you know this is crazy, right? :-)

1) copy & paste would be really annoying (on that note, Xcode should totally get multiple cursors support like in Sublime)

2) any non-specialized syntax highlighter would parse them all completely incorrectly, which is not a show-stopper, but shouldn't be taken lightly. (Think a generic indented code block in Markdown on GitHub.)

3) it's just cruel — xkcd: (

A.

Yes, you are right, Brent, there should be a closing quote on the last line otherwise it would be a syntax error. That’s a much better idea! That would also fix the

let x = “foo

being valid syntax problem.

Guys, you know this is crazy, right? :-)

1) copy & paste would be really annoying (on that note, Xcode should totally get multiple cursors support like in Sublime)

2) any non-specialized syntax highlighter would parse them all completely incorrectly, which is not a show-stopper, but shouldn't be taken lightly. (Think a generic indented code block in Markdown on GitHub.)

3) it's just cruel — xkcd: (

Haha, perhaps it is cruel. Just think of it as a closing quote out at infinity. ;-)

Tyler

···

On Dec 14, 2015, at 2:21 PM, Andrey Tarantsov <andrey@tarantsov.com> wrote:

<(.png>

A.