[swift-evolution] Fwd: Alternate proposal for multi-line string literial

Steve K. Chiu steve.k.chiu at gmail.com
Thu Mar 24 08:43:14 CDT 2016


Perl are using heredoc notation, for example:

my $message = <<'END_MESSAGE';
void main() {
     printf("%s\n", "hello world");
}
END_MESSAGE

or Perl6

https://doc.perl6.org/language/quoting

Lua's multi-line raw string look like this:
(you can add extra = inside [[ and ]], in case the text contains [[ or ]])

local message = [[
void main() {
     printf("%s\n", "hello world");
}
]]

or with ]] in text:

local message = [===[
void main() {
     printf("[[%s]]\n", "hello world");
}
]===]

And C++11 raw string has the same mechanism as Lua (but does not remove
first/last newline)

auto message = R"(void main() {
     printf("[[%s]]\n", "hello world");
})";

or with )" in text:

auto message = R"===(void main() {
     printf("(%s)", "hello world");
})===";


I think adding extra tag inside the string deliminator is actually a good
idea, I would like to revise the proposal as:

#string(options) ``text``

And then you can add extra tag inside back-quote, just like Lua and C++11
raw strings, so the shortest version would look like:

``^\d+``

It is raw string (escape is disabled), useful for regexp immediately, and
if you need to write `` inside the string:

let message =
`==`
void main() {
     printf("``(%s)``", "hello world");
}
`==`

or with options:

let message =
#string(escape: "$")
``
void main() {
     printf("(%s)", "$(value)");
}
``




2016-03-24 19:46 GMT+08:00 Step C <schristopher at bignerdranch.com>:

> Happy to see someone with a proposal on this!
>
> > On Mar 23, 2016, at 12:49 AM, Steve K. Chiu via swift-evolution <
> swift-evolution at swift.org> wrote:
> >
> > Hi,
> >
> > I am new to swift-evolution list, here is my draft proposal for the
> multi-line string literal problem.
> > The idea had been discussed in the list before, but it seems there are
> no real solution to many of the string literal problem.
> > Let's first define what are the problem with string literal:
> >
> > 1. should be able to disable escape char
> >
> > 2. or better, able to replace escape char with user defined char
> Yes!
> >
> > 3. should be able to write multi-line string literal, and is copy-paste
> friendly
> >
> > 4. for multi-line string, should be  able to remove first and last
> newline char, so user can write string in block
> >
> > 5. for multi-line string, should be  able to remove leading indent, or
> remove all indent
> >
> > 6. for multi-line string, should be  able to replace newline with user
> defined string ("\r\n", "\r", "\r", or simply " ")
> >
> > 7. should be able to add feature over time, without breaking existing
> code
> >
> > My proposal to the above problem is to introduce new 'process
> instruction' (not sure how to call it), in the following form:
> >
> > #string(options) "text"
>
> Building on our meaning for # as compile-time magic. Ok.
> >
> > for example:
> >
> > #string(escape: nil) "^\d+"
> >
> > #string(escape: "$", end: "<EOF>") "
> >    $(username),
> >    Is it 1358 yet?
> > <EOF>"
> >
> > It is possible to add many options list above, and you can add more
> options over time without breaking code.
> >
> > #string(
> >     escape: Character? = "\\",
> >     end: String? = nil,
> >     skipEnclosureNewline: Bool = true,
> >     skipLeadingIndent: Bool = true,
> >     skipAllIndent: Bool = false,
> >     newline: String? = nil
> > )
> >
> > for 1. & 2., escape option to replace escape char, pass nil will disable
> escape.
> >
> > for 3., end option for end-of-string mark, pass nil will disable
> multi-line processing.
> >
> > for 4., skipEnclosureNewline will skip newline if it is the first or
> last char of the string.
> >
> > for 5., skipLeadingIndent will skip leading indent, leading indent is
> the leading white-spaces of first line of multi-line string.
> >
> > for 5., skipAllIndent will skip all indent, this will override
> skipLeadingIndent.
> >
> > for 6., newline option to replace newline char in multi-line string,
> pass nil will disable the replacement (as-is in the source).
> >
> > But there are one problem remain, as you can see, the #string with
> options will become very long; I don't think it is a pleasure to use such
> expression except for one time literal. To fix the problem, I propose yet
> another process instruction:
> >
> > #let #rex = #string(escape: nil)
> > #let #mail = #string(escape: "$", end: "<EOF>")
> >
> > Now you can write the string as:
> >
> > #rex "^\d+"
> >
> > #mail "
> >    $(username),
> >    Is it 1358 yet?
> > <EOF>"
> >
> > #let should be able to be used with other # process instruction as well,
> for example, #available, among other things.
> >
> > What do you think?
>
> I'd like to see a comparison to how other languages, particularly Perl,
> handle this. I like Chris Lattner's vision for this to be the power-user
> version of string literals. As you identified, a problem with this solution
> is verbosity / noisiness. I don't like the #let #token syntax on first
> blush - seems macro-ish to me. But I don't have a better suggestion right
> now. Hmmm.
>
>
> >
> >
> > _______________________________________________
> > swift-evolution mailing list
> > swift-evolution at swift.org
> > https://lists.swift.org/mailman/listinfo/swift-evolution
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160324/ad4cae41/attachment.html>


More information about the swift-evolution mailing list