[swift-evolution] [Review] SE-0168: Multi-Line String Literals
Xiaodi Wu
xiaodi.wu at gmail.com
Thu Apr 13 18:48:18 CDT 2017
On Thu, Apr 13, 2017 at 4:03 AM, Brent Royal-Gordon <brent at architechies.com>
wrote:
> On Apr 12, 2017, at 5:39 PM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>
> On Wed, Apr 12, 2017 at 5:20 PM, Brent Royal-Gordon <
> brent at architechies.com> wrote:
>
>> Wow, maybe I shouldn't have slept.
>>
>> Okay, let's deal with trailing newline first. I'm *very* confident that
>> trailing newlines should be kept by default. This opinion comes from lots
>> of practical experience with multiline string features in other languages.
>> In practice, if you're generating files in a line-oriented way, you're
>> usually generating them a line at a time. It's pretty rare that you want to
>> generate half a line and then add more to it in another statement; it's
>> more likely you'll interpolate the data. I'm not saying it doesn't happen,
>> of course, but it happens a lot less often than you would think just
>> sitting by the fire, drinking whiskey and musing over strings.
>>
>> I know that, if you're pushing for this feature, it's not satisfying to
>> have the answer be "trust me, it's not what you want". But trust me, it's
>> not what you want.
>>
>
> This is not a very good argument. If you are generating files in a
> line-oriented way, it is the function _emitting_ the string that handles
> the line-orientedness, not the string itself. That is the example set by
> `print()`:
>
> ```
> print("Hello, world!") // Emits "Hello, world!\n"
> ```
>
>
> You say "this is the example set by `print`", but I don't think anything
> else actually *follows* that example. No other I/O operation in Swift
> behaves this way.
>
To be more accurate, it's not `print` that specifies this behavior, but
rather the standard output stream's implementation of
`TextOutputStream.write(_:)`. Swift *explicitly* leaves this choice up to
the TextOutputStream-conforming type. That is, the behavior is up to the
receiver and not the argument of a call to `TextOutputStream.write(_:)`.
The underlying `TextOutputStream.write(_:)` doesn't; the I/O in Foundation
> doesn't; file descriptor I/O doesn't.
>
And this goes to my point: there is line-oriented I/O, and there is
non-line-oriented I/O. After all, why would I/O operations designed to
write arbitrary bytes emit trailing newlines by default? It is the I/O
operation that determines whether trailing newlines are implied or not,
*not* the string.
Concatenation certainly doesn't; nor does anything else you might do to
> assemble several multiline string literals into a whole.
>
And this goes to my other point: it *shouldn't*, because there is nothing
about concatenation that is specifically "line-oriented." I am not aware of
any language that concatenates with `+` which infers a default separator.
Anyone who has ever used `+` has *always* appended their own separator.
That is the user expectation, not what you show below.
So I think `print()` is the exception here, not the rule.
>
> In my opinion, modulo the "newline after leading delimiter" question, if
> code like this example:
>
> var xml = """
> <?xml version="1.0"?>
> <catalog>
> """
> for (id, author, title, genre, price) in bookTuples {
> xml += """
> <book id="bk\(id)">
> <author>\(author)</author>
> <title>\(title)</title>
> <genre>\(genre)</genre>
> <price>\(price)</price>
> </book>
> """
> }
> xml += """
> </catalog>
> """
>
> Doesn't assemble the kind of string that it's blatantly obvious the user
> is trying to assemble, I think the syntax has failed.
>
First, let's be clear that this is an argument against your proposed
no-newline-stripping-anywhere rule, so clearly this is not the motivating
use case for that proposed design. I see you've moved away from it.
Second, this is a circular argument, where you are asserting that your
proposed no-trailing-newline-stripping is the only blatantly obvious
meaning because it is blatantly obvious. On the contrary, it is not at all
clear to me that the user obviously wants a newline, not any more so than
the following, which clearly does not and should not insert newlines:
```
var xml = "<?xml version=\"1.0\"?>"
xml += "<catalog>"
for (id, _, _, _, _) in bookTuples {
xml += "<book id=\"bk\(id)\">Book ID: \(id)</book>"
}
xml += "</catalog>"
```
To me, the only blatantly obvious behavior is that if you're going to want
a separator and you're using `+` or `+=` for string concatenation, you
concatenate the separator yourself. Why would that change just because
there's multiline string syntax? The only thing that multiline string
syntax should _maybe_ suggest to the reader is that there's a decent chance
that there's a newline somewhere in the string, *not* that there's a decent
chance that the string ends with one.
`print()` is the outlier. It's an important enough outlier that we should
> probably help the user notice when they're about to get it wrong, but an
> outlier it is.
>
> --
> Brent Royal-Gordon
> Architechies
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170413/9a732a9c/attachment.html>
More information about the swift-evolution
mailing list