I’m converting a previously concatenated string to the new multi-line string syntax. It contains signifiant whitespace at the end of lines, so I have to use \n\
to explicitly properly terminate the line where it should be, to protect it from editor (Xcode) that strips the whitespace from the end of the line. Problem is with the last line, where I don’t want the newline to be part of the string, but cannot use just a single \
because it gives me error:
Escaped newline at the last line is not allowed
Fix offered by Xcode looked suspicious...
...but I clicked it anyway, to have my string corrupted (removing leading whitespace and just stripping the \
).
In searching for solution I have looked at following sources:
- Official documentation and found nothing.
- SE-0168 and found nothing.
- Implementation of SE-0168 in PR #8813 and found nothing, even though the tests for multiline-errors looked promising.
- Looked at SE-0168 acceptance decision from the core team and found:
- Searched Swift Evolution and found SE-0182 String Newline Escaping, which says:
An escape character at the end of the last line of a literal is an error, as no newlines follow.
… which is a consequence of the implementation using regular-expression: /\\[ \t]*\n/
.
- Objection to this side effect was raised during proposal review:
- This was noted in proposal acceptance announcement, but the core team simply stated agreement with proposed design without offering any justification:
- First PR implementing of SE-0182 didn’t even enforce the escape character at the end of last line as error.
- The enforcement was added in a separate pull request.
Reasons for Status Quo
My impression is that we currently have two rules for multiline strings:
- remove newlines following and preceding the
"""
delimiter - remove (whitespace and) newline following the
\
Theoretically they can create a conflict, when we put the \
on last line before the """
delimiter, this wants to consume two newlines where there’s only one.
But in my opinion this is completely harmless. I can not think of a situation where this is a genuine error. I see no point in enforcing this rule. From cursory look at the implementation, my impression is that PR #11199 had to add extra complexity on top of initial SE-0182 implementation just to enforce the third rule from the proposal. In my opinion, the third rule, even though technically correct consequence of judicious regex application, is entirely unnecessary.
In fact it keeps me from writing a multi-line string with significant whitespace at the end, without a newline in natural way:
let asciiArt = """
\ / \n\
V \
"""
Current Workaround
Reading back through the discussion of [Accepted] SE-0168, where the issues related to trailing whitespace were raised before, I found this idea (from a completely different context), that offers a workaround for my issue:
So the first workaround I found after the multi-hour, above-documented, research ordeal was to abuse string interpolation:
let asciiArt = """
\ / \n\
V \("")
"""
Thinking more about the rules, it finally downed on me that to write a multiline string that ends with significant whitespace and doesn’t contain a trailing newline, I have to insert one more newline:
let asciiArt = """
\ / \n\
V \
"""
Questions About Future
Is the current implementation in desired state? If yes, I should probably post my workaround to Stack Overflow to save other Swift programmers hours of frustration.
Can we do better and just drop the pointless rule and its enforcement?