multi-line string literals


(Travis Tilley) #1

I would very much like to implement multi-line string literals in swift and
get feedback on what this should look like, as i've been informed there are
several competing suggestions filed as radars.

My initial improvement request is here: https://bugs.swift.org/browse/SR-170

It is only an opinion, but it's my belief that simple python-style
multi-line string literals are the way to go. They're simple and, in the
end, exactly the same as normal string literals. They begin and end with
triple quotes, can contain newlines, can contain single quotes, and that's
all that's special in their parsing. The same block of code in Lexer.cpp
could be used for both types of literal, ensuring behavior is always
consistent regardless of any future changes.

There is also the potential suggestion of removing consistent indentation
if there is any so as to make formatting of a multi-line string literal
look more clean when indented. For me, it would be a nice to have, but not
a make or break feature... and for some it may be confusing.

I'd like to state that I'm not proposing heredoc-style functionality, as I
believe that to be an entirely separate feature. The potential to have one
heredoc embedded within another would certainly make parsing more painful
than i'm happy with.

For an example of code that would benefit significantly from multi-line
string literals, please look at docopt.swift:
https://github.com/docopt/docopt.swift/blob/master/Examples/Swift/arguments_example/main.swift#L9-L25

Docopt does the opposite of what most command line argument libraries do:
rather than defining options and auto-generating the help text based on
that... You write the help text and it auto-generates a CLI with exactly
those options and arguments. It makes writing CLI applications an absolute
pleasure, but without multi-line string literals in swift it's currently
less pleasant than it could be.

Please send me your thoughts. ^_^b

-Travis Tilley


(Casey Cady) #2

I would very much like to implement multi-line string literals in swift and get feedback on what this should look like, as i've been informed there are several competing suggestions filed as radars.

My initial improvement request is here: https://bugs.swift.org/browse/SR-170

It is only an opinion, but it's my belief that simple python-style multi-line string literals are the way to go. They're simple and, in the end, exactly the same as normal string literals. They begin and end with triple quotes, can contain newlines, can contain single quotes, and that's all that's special in their parsing. The same block of code in Lexer.cpp could be used for both types of literal, ensuring behavior is always consistent regardless of any future changes.

There is also the potential suggestion of removing consistent indentation if there is any so as to make formatting of a multi-line string literal look more clean when indented. For me, it would be a nice to have, but not a make or break feature... and for some it may be confusing.

I'd like to state that I'm not proposing heredoc-style functionality, as I believe that to be an entirely separate feature. The potential to have one heredoc embedded within another would certainly make parsing more painful than i'm happy with.

For an example of code that would benefit significantly from multi-line string literals, please look at docopt.swift: https://github.com/docopt/docopt.swift/blob/master/Examples/Swift/arguments_example/main.swift#L9-L25

Docopt does the opposite of what most command line argument libraries do: rather than defining options and auto-generating the help text based on that... You write the help text and it auto-generates a CLI with exactly those options and arguments. It makes writing CLI applications an absolute pleasure, but without multi-line string literals in swift it's currently less pleasant than it could be.

Please send me your thoughts. ^_^b

-Travis Tilley

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

···

Sent from my iPhone

On Dec 10, 2015, at 1:56 PM, Travis Tilley via swift-evolution <swift-evolution@swift.org> wrote:


(Casey Cady) #3

I really like the idea but I wonder how this would interact with NSLocalizedString exporting within XCode.

···

On Dec 10, 2015, at 1:56 PM, Travis Tilley via swift-evolution <swift-evolution@swift.org> wrote:

I would very much like to implement multi-line string literals in swift and get feedback on what this should look like, as i've been informed there are several competing suggestions filed as radars.

My initial improvement request is here: https://bugs.swift.org/browse/SR-170

It is only an opinion, but it's my belief that simple python-style multi-line string literals are the way to go. They're simple and, in the end, exactly the same as normal string literals. They begin and end with triple quotes, can contain newlines, can contain single quotes, and that's all that's special in their parsing. The same block of code in Lexer.cpp could be used for both types of literal, ensuring behavior is always consistent regardless of any future changes.

There is also the potential suggestion of removing consistent indentation if there is any so as to make formatting of a multi-line string literal look more clean when indented. For me, it would be a nice to have, but not a make or break feature... and for some it may be confusing.

I'd like to state that I'm not proposing heredoc-style functionality, as I believe that to be an entirely separate feature. The potential to have one heredoc embedded within another would certainly make parsing more painful than i'm happy with.

For an example of code that would benefit significantly from multi-line string literals, please look at docopt.swift: https://github.com/docopt/docopt.swift/blob/master/Examples/Swift/arguments_example/main.swift#L9-L25

Docopt does the opposite of what most command line argument libraries do: rather than defining options and auto-generating the help text based on that... You write the help text and it auto-generates a CLI with exactly those options and arguments. It makes writing CLI applications an absolute pleasure, but without multi-line string literals in swift it's currently less pleasant than it could be.

Please send me your thoughts. ^_^b

-Travis Tilley

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


(Chris Lattner) #4

I would very much like to implement multi-line string literals in swift and get feedback on what this should look like, as i've been informed there are several competing suggestions filed as radars.

I’m positive about adding some syntax for multi-line string literals. Some questions to think about and debate on this list:

1) What concrete syntax should be used? There are a lot of options in this space across a wide range of languages. C++ has raw strings, and this page has more examples:
http://rigaux.org/language-study/syntax-across-languages.html#StrngMltLine

2) Should escapes like \n be processed always, should they never be processed, or should they be processed by default but disable-able in the syntax?

3) What other policy decisions make sense to expose on these literals? Since this will be the “powerful form of string literals”, it makes sense to be the place to put weird knobs that are seldom used but important in various cases.

I assume that this would tie into the existing literal convertible protocols, and if/when escaping is supported that it would support interpolation as well.

-Chris

···

On Dec 10, 2015, at 1:56 PM, Travis Tilley via swift-evolution <swift-evolution@swift.org> wrote:

My initial improvement request is here: https://bugs.swift.org/browse/SR-170

It is only an opinion, but it's my belief that simple python-style multi-line string literals are the way to go. They're simple and, in the end, exactly the same as normal string literals. They begin and end with triple quotes, can contain newlines, can contain single quotes, and that's all that's special in their parsing. The same block of code in Lexer.cpp could be used for both types of literal, ensuring behavior is always consistent regardless of any future changes.

There is also the potential suggestion of removing consistent indentation if there is any so as to make formatting of a multi-line string literal look more clean when indented. For me, it would be a nice to have, but not a make or break feature... and for some it may be confusing.

I'd like to state that I'm not proposing heredoc-style functionality, as I believe that to be an entirely separate feature. The potential to have one heredoc embedded within another would certainly make parsing more painful than i'm happy with.

For an example of code that would benefit significantly from multi-line string literals, please look at docopt.swift: https://github.com/docopt/docopt.swift/blob/master/Examples/Swift/arguments_example/main.swift#L9-L25

Docopt does the opposite of what most command line argument libraries do: rather than defining options and auto-generating the help text based on that... You write the help text and it auto-generates a CLI with exactly those options and arguments. It makes writing CLI applications an absolute pleasure, but without multi-line string literals in swift it's currently less pleasant than it could be.

Please send me your thoughts. ^_^b

-Travis Tilley

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


(Tal Atlas) #5

Conceptually for this, especially for server side utility. I think there’s
a plethora of options out there, “”” seems to be the most modern one, and
i’d vote for it having the same interpolation as standard strings \()

···

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

I would very much like to implement multi-line string literals in swift
and get feedback on what this should look like, as i've been informed there
are several competing suggestions filed as radars.

My initial improvement request is here:
https://bugs.swift.org/browse/SR-170

It is only an opinion, but it's my belief that simple python-style
multi-line string literals are the way to go. They're simple and, in the
end, exactly the same as normal string literals. They begin and end with
triple quotes, can contain newlines, can contain single quotes, and that's
all that's special in their parsing. The same block of code in Lexer.cpp
could be used for both types of literal, ensuring behavior is always
consistent regardless of any future changes.

There is also the potential suggestion of removing consistent indentation
if there is any so as to make formatting of a multi-line string literal
look more clean when indented. For me, it would be a nice to have, but not
a make or break feature... and for some it may be confusing.

I'd like to state that I'm not proposing heredoc-style functionality, as I
believe that to be an entirely separate feature. The potential to have one
heredoc embedded within another would certainly make parsing more painful
than i'm happy with.

For an example of code that would benefit significantly from multi-line
string literals, please look at docopt.swift:
https://github.com/docopt/docopt.swift/blob/master/Examples/Swift/arguments_example/main.swift#L9-L25

Docopt does the opposite of what most command line argument libraries do:
rather than defining options and auto-generating the help text based on
that... You write the help text and it auto-generates a CLI with exactly
those options and arguments. It makes writing CLI applications an absolute
pleasure, but without multi-line string literals in swift it's currently
less pleasant than it could be.

Please send me your thoughts. ^_^b

-Travis Tilley

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


(Travis Tilley) #6

I am going to wait until friday the 18th to submit a formal swift-evolution
review for this feature. I'm not sure if a week is enough time to get the
feedback I need, but hopefully that will be the case. I'm quite new to the
project and this procedure. I'd certainly like to hear from more core team
members than just Chris Lattner, no matter how much of a badass he might
be. Hopefully my desire to keep things simple doesn't clash with the
community goals.

-Travis Tilley


(Brent Royal-Gordon) #7

I would very much like to implement multi-line string literals in swift and get feedback on what this should look like, as i've been informed there are several competing suggestions filed as radars.

Some principles:

1. You do not want to plop enormous multi-line string constants in the middle of expressions. This makes the expressions impossible to read. Instead, you want a placeholder for the string in the expression, and then the string on a separate line.

2. Having said that, when there are several placeholders, you also want it to be obvious which text goes with which placeholder.

3. You want a syntax which clearly indicates which indentation is meant to line up the string literal with the code, and which is meant to be *in* the string literal.

With these principles in mind, I suggest something like:

  onMessage(DAVE>, sendMessage: HAL>)
  >Open the pod bay doors,
  > HAL!
  >I’m sorry, Dave,
  > I’m afraid I can’t
  > do that.

A multiline literal reference consists of an identifier followed by a closing angle bracket in postfix operator position. After the end of any statement containing a multiline literal reference, Swift starts looking for the actual multiline literals mentioned in that statement. Leading whitespace is consumed and discarded up to a matching identifier and angle bracket; the text on the line after the literal, up to the newline, is the text of the literal. Once Swift encounters a line that doesn’t start with whitespace, an identifier, and an angle bracket, it switches back to looking for ordinary statements.

(By the way, the all-caps is a stylistic suggestion, not a requirement, and I’m not at all sure it’s the *right* stylistic suggestion.)

As a shorthand for lines with only one string, you might be able to say:

  sendMessage(_>)
  >I’m sorry, Dave,
  > I’m afraid I can’t
  > do that.

While this solves the indentation problem, it doesn’t answer the question of whether the trailing \n is part of the literal. I think it is. I’m actually tempted to say that *all* newlines are ignored and you need \n if you want a real newline, but that seems like it would do a lot of violence to the entire concept of a multiline literal.

···

--
Brent Royal-Gordon
Architechies


(Kenny Leung) #8

How about this: a pseudo-function that will just include the contents of another file into your code?

let bigString = StringLiteral(“MyLifeStory”)

You have another file called “MyLifeStory.swiftstring” alongside your source file. Then there is no thinking about escaping, line endings, etc. Anything in that file is processed as the string.

-Kenny


(Travis Tilley) #9

If implemented as an argument to `Lexer::lexStringLiteral()`, then it would
behave exactly like a typical string literal except where multi-line
behavior is concerned (and being terminated by triple quotes instead of a
single quote). This would include interpolation, as well as any future
functionality.

The function in question wouldn't require much modification:
https://github.com/apple/swift/blob/0bfba2972ec718bb23c006d5fdd9736c506f681e/lib/Parse/Lexer.cpp#L1121

As well as slight modification here to detect triple quoted strings and
pass on that information:
https://github.com/apple/swift/blob/0bfba2972ec718bb23c006d5fdd9736c506f681e/lib/Parse/Lexer.cpp#L1654-L1656

But that would be an implementation detail, and only if others agree to
using triple quote syntax.

- Travis Tilley

···

On Thu, Dec 10, 2015 at 5:43 PM, Tal Atlas <me@tal.by> wrote:

Conceptually for this, especially for server side utility. I think there’s
a plethora of options out there, “”” seems to be the most modern one, and
i’d vote for it having the same interpolation as standard strings \()

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

I would very much like to implement multi-line string literals in swift
and get feedback on what this should look like, as i've been informed there
are several competing suggestions filed as radars.

My initial improvement request is here:
https://bugs.swift.org/browse/SR-170

It is only an opinion, but it's my belief that simple python-style
multi-line string literals are the way to go. They're simple and, in the
end, exactly the same as normal string literals. They begin and end with
triple quotes, can contain newlines, can contain single quotes, and that's
all that's special in their parsing. The same block of code in Lexer.cpp
could be used for both types of literal, ensuring behavior is always
consistent regardless of any future changes.

There is also the potential suggestion of removing consistent indentation
if there is any so as to make formatting of a multi-line string literal
look more clean when indented. For me, it would be a nice to have, but not
a make or break feature... and for some it may be confusing.

I'd like to state that I'm not proposing heredoc-style functionality, as
I believe that to be an entirely separate feature. The potential to have
one heredoc embedded within another would certainly make parsing more
painful than i'm happy with.

For an example of code that would benefit significantly from multi-line
string literals, please look at docopt.swift:
https://github.com/docopt/docopt.swift/blob/master/Examples/Swift/arguments_example/main.swift#L9-L25

Docopt does the opposite of what most command line argument libraries do:
rather than defining options and auto-generating the help text based on
that... You write the help text and it auto-generates a CLI with exactly
those options and arguments. It makes writing CLI applications an absolute
pleasure, but without multi-line string literals in swift it's currently
less pleasant than it could be.

Please send me your thoughts. ^_^b

-Travis Tilley

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


(Travis Tilley) #10

I have no idea how genstrings and so forth work, but if they actually parse
the code (which seems likely), then they'll be getting back the same AST
they would for normal strings (since this feature would be implemented
pretty much entirely in the swift lexer).

If I am wrong, someone please correct me. I'm non-apple and don't know how
all of this works. :wink:

-Travis Tilley

···

On Thu, Dec 10, 2015 at 8:12 PM, Casey Cady <casey@kckd.org> wrote:

I really like the idea but I wonder how this would interact with
NSLocalizedString exporting within XCode.


(Travis Tilley) #11

1) What concrete syntax should be used? There are a lot of options in
this space across a wide range of languages. C++ has raw strings, and this
page has more examples:
http://rigaux.org/language-study/syntax-across-languages.html#StrngMltLine

​I am open to any and all suggestions, though I've already stated my
personal fondness for python's style. ;)​

2) Should escapes like \n be processed always, should they never be
processed, or should they be processed by default but disable-able in the
syntax?

I would want multi-line string literals to behave as much like normal
string literals as possible for consistency. To optimize for developer
happiness, to steal the ruby saying, unexpected behavior should be kept to
a minimum. If \n works in a normal string literal, it should work in a
multi-line string literal... even if you could just hit enter instead.

3) What other policy decisions make sense to expose on these literals?
Since this will be the “powerful form of string literals”, it makes sense
to be the place to put weird knobs that are seldom used but important in
various cases.

​I would have to depend entirely on you to inform me of both these knobs
and use cases. ​I'd love to hear about them, that's for sure.

My initial goal was the minimal possible work required to decrease the
noise of writing large blocks of multi-line text and not have to poke
around too much in the lexer and parser code (being completely unfamiliar
with the swift codebase, having it just become open source recently).

I assume that this would tie into the existing literal convertible
protocols, and if/when escaping is supported that it would support
interpolation as well.

​I actually wanted to re-use the same function for handling normal string
literals so that the functionality available would be exactly the same, and
the output would be the exact same `​tok::string_literal`.

- Travis Tilley

···

On Thu, Dec 10, 2015 at 8:41 PM, Chris Lattner <clattner@apple.com> wrote:


(Travis Tilley) #12

I'm not entirely sure how to respond to this, but I think some of your
suggestions might go against the goal of having less noise in defining a
multi-line string. It's actually more to type than:

"this is the first line \n" +
"this is the second line \n"

​...which we can already do.

Your suggestion that each line should end in \n makes me think you're
actually trying to have a bit of fun with me, but I can't really tell and I
really don't want to be rude by making that assumption.

···

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

> I would very much like to implement multi-line string literals in swift
and get feedback on what this should look like, as i've been informed there
are several competing suggestions filed as radars.

Some principles:

1. You do not want to plop enormous multi-line string constants in the
middle of expressions. This makes the expressions impossible to read.
Instead, you want a placeholder for the string in the expression, and then
the string on a separate line.

2. Having said that, when there are several placeholders, you also want it
to be obvious which text goes with which placeholder.

3. You want a syntax which clearly indicates which indentation is meant to
line up the string literal with the code, and which is meant to be *in* the
string literal.

With these principles in mind, I suggest something like:

        onMessage(DAVE>, sendMessage: HAL>)
        >Open the pod bay doors,
        > HAL!
        >I’m sorry, Dave,
        > I’m afraid I can’t
        > do that.

A multiline literal reference consists of an identifier followed by a
closing angle bracket in postfix operator position. After the end of any
statement containing a multiline literal reference, Swift starts looking
for the actual multiline literals mentioned in that statement. Leading
whitespace is consumed and discarded up to a matching identifier and angle
bracket; the text on the line after the literal, up to the newline, is the
text of the literal. Once Swift encounters a line that doesn’t start with
whitespace, an identifier, and an angle bracket, it switches back to
looking for ordinary statements.

(By the way, the all-caps is a stylistic suggestion, not a requirement,
and I’m not at all sure it’s the *right* stylistic suggestion.)

As a shorthand for lines with only one string, you might be able to say:

        sendMessage(_>)
        >I’m sorry, Dave,
        > I’m afraid I can’t
        > do that.

While this solves the indentation problem, it doesn’t answer the question
of whether the trailing \n is part of the literal. I think it is. I’m
actually tempted to say that *all* newlines are ignored and you need \n if
you want a real newline, but that seems like it would do a lot of violence
to the entire concept of a multiline literal.

--
Brent Royal-Gordon
Architechies


(Riley Avron) #13

How about this: a pseudo-function that will just include the contents of
another file into your code?
let bigString = StringLiteral(“MyLifeStory”)
You have another file called “MyLifeStory.swiftstring” alongside your
source file. Then there is no thinking about escaping, line endings, etc.
Anything in that file is processed as the string.

This makes sense for truly long strings, but could get unwieldy in the case
of a handful of strings spanning a few lines each, which I would posit is
the more common case.

Riley

···

On 14 December 2015 at 10:56, Kenny Leung via swift-evolution < swift-evolution@swift.org> wrote:

How about this: a pseudo-function that will just include the contents of
another file into your code?

let bigString = StringLiteral(“MyLifeStory”)

You have another file called “MyLifeStory.swiftstring” alongside your
source file. Then there is no thinking about escaping, line endings, etc.
Anything in that file is processed as the string.

-Kenny

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


(Casey Cady) #14

Keep in mind that there's both genstrings and the new xliff exporter, and the latter was a hot mess for quite a while and only recently started working properly, so I have zero confidence that it would just work. But as you say, we really do need someone from Apple to weigh in. :slight_smile:

···

Sent from my iPhone

On Dec 10, 2015, at 5:42 PM, Travis Tilley <ttilley@gmail.com> wrote:

I have no idea how genstrings and so forth work, but if they actually parse the code (which seems likely), then they'll be getting back the same AST they would for normal strings (since this feature would be implemented pretty much entirely in the swift lexer).

If I am wrong, someone please correct me. I'm non-apple and don't know how all of this works. :wink:

-Travis Tilley

On Thu, Dec 10, 2015 at 8:12 PM, Casey Cady <casey@kckd.org> wrote:
I really like the idea but I wonder how this would interact with NSLocalizedString exporting within XCode.


(Chris Lattner) #15

2) Should escapes like \n be processed always, should they never be processed, or should they be processed by default but disable-able in the syntax?

I would want multi-line string literals to behave as much like normal string literals as possible for consistency. To optimize for developer happiness, to steal the ruby saying, unexpected behavior should be kept to a minimum. If \n works in a normal string literal, it should work in a multi-line string literal... even if you could just hit enter instead.

Yes, I agree that should be the default.

3) What other policy decisions make sense to expose on these literals? Since this will be the “powerful form of string literals”, it makes sense to be the place to put weird knobs that are seldom used but important in various cases.

​I would have to depend entirely on you to inform me of both these knobs and use cases. ​I'd love to hear about them, that's for sure.

The reason I raise the question is that some languages have multiple quote styles (Perl 5 has something like 3 or 4 different string literal styles IIRC?) with different policies. One reason for this is to disable processing of escapes: if you’re using string literals to enter something that uses \ or “ frequently, it can be irritating and ugly to have a lot of \\'s <smb://'s>. In some dialects of inline assembly in C, for example, this can lead to very ugly code.

When introducing a feature like this, I think it would be useful to survey a range of popular languages (and yes, even perl ;-) to understand what facilities they provide and why (i.e. what problems they are solving) and synthesize a good swift design that can solve the same problems with a hopefully simple approach.

I haven’t looked into this area deeply myself, so I can’t give you a recipe to just follow, some research is required :)

My initial goal was the minimal possible work required to decrease the noise of writing large blocks of multi-line text and not have to poke around too much in the lexer and parser code (being completely unfamiliar with the swift codebase, having it just become open source recently).

Understood, but our first goal is to get the best solution, independent of implementation complexity. In this case, I suspect that the hard part in this feature is scoping it out and hashing out the right design with the community. I can’t imagine that we’d end up with a design that is that difficult to implement in any case.

-Chris

···

On Dec 10, 2015, at 6:01 PM, Travis Tilley <ttilley@gmail.com> wrote:


(Jason Dusek) #16

What do you all think about automatic dedenting of these literals? The
excess whitespace is rarely useful; and usually spawns a dedent function
which comes to decorate all such strings.

I have no idea how genstrings and so forth work, but if they actually parse

the code (which seems likely), then they'll be getting back the same AST
they would for normal strings (since this feature would be implemented
pretty much entirely in the swift lexer).

If I am wrong, someone please correct me. I'm non-apple and don't know how
all of this works. :wink:

-Travis Tilley

I really like the idea but I wonder how this would interact with
NSLocalizedString exporting within XCode.

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

···

On Thu, 10 Dec 2015 at 17:43 Travis Tilley via swift-evolution swift-evolution@swift.org <http://mailto:swift-evolution@swift.org> wrote:

On Thu, Dec 10, 2015 at 8:12 PM, Casey Cady <casey@kckd.org> wrote:


(Brent Royal-Gordon) #17

I'm not entirely sure how to respond to this, but I think some of your suggestions might go against the goal of having less noise in defining a multi-line string. It's actually more to type than:
"this is the first line \n" +
"this is the second line \n"
​...which we can already do.

Your suggestion that each line should end in \n makes me think you're actually trying to have a bit of fun with me, but I can't really tell and I really don't want to be rude by making that assumption.

I am being serious. This proposal does require more characters, it’s true. However, it doesn’t require more *reading*—because the leading indicators will generally line up, you can ignore them and read everything to the right, like the “> “ used to demarcate your text above from my text—and with an editor feature to select several lines and quote them (the way you can with comments in most editors), it wouldn’t require more *writing* either. And although it uses more characters, it *also* unmistakably sets off quoted material from code, comments, other multiline string literals, and anything else, while being unambiguous about whether indentation is intended to style the literal or be part of it, without a bunch of funky obscure modifier characters like "<<-END".

The \n thing was an idle thought being presented for discussion, not a concrete suggestion, but it was also not a joke. (I realized after sending it, however, that the trailing newline problem can be solved by simply having a rule that you strip one trailing newline. If you want your string to end with a newline, include a sacrificial blank “Foo>” line at the end of the literal. Some sort of modifier to indicate the trailing newline behavior is possible too, but see the previous paragraph for my thoughts on those.)

I’ve used and loved heredocs in Perl and Ruby, but I always understood that they have significant problems. That experience shaped this proposal.

···

--
Brent Royal-Gordon
Architechies


(Travis Tilley) #18

Ah. My sincerest apologies for making that assumption then.

Your suggestion doesn't solve my use case, personally. I'm also *hoping* to
officially propose something less complex than heredocs once there's been
enough feedback.

-Travis Tilley

···

On Fri, Dec 11, 2015 at 5:52 PM, Brent Royal-Gordon <brent@architechies.com> wrote:

> I'm not entirely sure how to respond to this, but I think some of your
suggestions might go against the goal of having less noise in defining a
multi-line string. It's actually more to type than:
> "this is the first line \n" +
> "this is the second line \n"
> ​...which we can already do.
>
> Your suggestion that each line should end in \n makes me think you're
actually trying to have a bit of fun with me, but I can't really tell and I
really don't want to be rude by making that assumption.

I am being serious. This proposal does require more characters, it’s true.
However, it doesn’t require more *reading*—because the leading indicators
will generally line up, you can ignore them and read everything to the
right, like the “> “ used to demarcate your text above from my text—and
with an editor feature to select several lines and quote them (the way you
can with comments in most editors), it wouldn’t require more *writing*
either. And although it uses more characters, it *also* unmistakably sets
off quoted material from code, comments, other multiline string literals,
and anything else, while being unambiguous about whether indentation is
intended to style the literal or be part of it, without a bunch of funky
obscure modifier characters like "<<-END".

The \n thing was an idle thought being presented for discussion, not a
concrete suggestion, but it was also not a joke. (I realized after sending
it, however, that the trailing newline problem can be solved by simply
having a rule that you strip one trailing newline. If you want your string
to end with a newline, include a sacrificial blank “Foo>” line at the end
of the literal. Some sort of modifier to indicate the trailing newline
behavior is possible too, but see the previous paragraph for my thoughts on
those.)

I’ve used and loved heredocs in Perl and Ruby, but I always understood
that they have significant problems. That experience shaped this proposal.

--
Brent Royal-Gordon
Architechies


(Marc Knaup) #19

Speaking of line endings…

"""
Line1
Line2
Line3
"""

On Mac/Unix the lines in the source file would likely end in \n while on
Windows the would likely end in \r\n.
What line endings would the resulting string have? The one from the source
file or would it be normalized to \n?

···

On Fri, Dec 11, 2015 at 11:31 PM, Travis Tilley via swift-evolution < swift-evolution@swift.org> wrote:

I'm not entirely sure how to respond to this, but I think some of your
suggestions might go against the goal of having less noise in defining a
multi-line string. It's actually more to type than:

"this is the first line \n" +
"this is the second line \n"

​...which we can already do.

Your suggestion that each line should end in \n makes me think you're
actually trying to have a bit of fun with me, but I can't really tell and I
really don't want to be rude by making that assumption.

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

> I would very much like to implement multi-line string literals in swift
and get feedback on what this should look like, as i've been informed there
are several competing suggestions filed as radars.

Some principles:

1. You do not want to plop enormous multi-line string constants in the
middle of expressions. This makes the expressions impossible to read.
Instead, you want a placeholder for the string in the expression, and then
the string on a separate line.

2. Having said that, when there are several placeholders, you also want
it to be obvious which text goes with which placeholder.

3. You want a syntax which clearly indicates which indentation is meant
to line up the string literal with the code, and which is meant to be *in*
the string literal.

With these principles in mind, I suggest something like:

        onMessage(DAVE>, sendMessage: HAL>)
        >Open the pod bay doors,
        > HAL!
        >I’m sorry, Dave,
        > I’m afraid I can’t
        > do that.

A multiline literal reference consists of an identifier followed by a
closing angle bracket in postfix operator position. After the end of any
statement containing a multiline literal reference, Swift starts looking
for the actual multiline literals mentioned in that statement. Leading
whitespace is consumed and discarded up to a matching identifier and angle
bracket; the text on the line after the literal, up to the newline, is the
text of the literal. Once Swift encounters a line that doesn’t start with
whitespace, an identifier, and an angle bracket, it switches back to
looking for ordinary statements.

(By the way, the all-caps is a stylistic suggestion, not a requirement,
and I’m not at all sure it’s the *right* stylistic suggestion.)

As a shorthand for lines with only one string, you might be able to say:

        sendMessage(_>)
        >I’m sorry, Dave,
        > I’m afraid I can’t
        > do that.

While this solves the indentation problem, it doesn’t answer the question
of whether the trailing \n is part of the literal. I think it is. I’m
actually tempted to say that *all* newlines are ignored and you need \n if
you want a real newline, but that seems like it would do a lot of violence
to the entire concept of a multiline literal.

--
Brent Royal-Gordon
Architechies

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


(Travis Tilley) #20

That would be my preference, especially since I can be lazy and re-use the
existing indentation detection code in Lexer.cpp. However, one could argue
that it could be confusing if indentation was intentional so I'd like to
hear more people weigh in on that one, especially core team members.

- Travis Tilley

···

On Thu, Dec 10, 2015 at 8:46 PM, Jason Dusek <jason.dusek@gmail.com> wrote:

What do you all think about automatic dedenting of these literals? The
excess whitespace is rarely useful; and usually spawns a dedent function
which comes to decorate all such strings.