Multiline string literals: can we get rid of the need for stripMargin?

Please do not forget this use case:

"""
    one
    "two"
    three
  """

I really like this about """ now. Same example with escaping single quotes:

"
    one
   \"two\"
    three
  "
4 Likes

``` would allow preserving the current semantics of """ and ", and avoid the need to quote embedded single quotes:

```
    one
    "two"
    three
  ```

There are other alternatives for creating a fenced block that could be worth exploring, like the heredoc:

val multiLineString = <<<EOF
    one
    "two"
    three
  EOF

println(<<<EOF
    one
    "two"
    three
  EOF
)

Yes, but the problem is that we cannot change the semantics of """ and we will not introduce a third quote such as ```. So that leaves us with multiline " which is still available. But having to escape quotes at start of lines is not nice, I agree.

One solution to this would be to use the existing stripMargin. I.e. you could write the example like this:

  "
  |one
  |"two"
  |three
  ".stripMargin

That’s just the old stripMargin we have, used in the new context.

heredoc idea looks interesting and could be changed a bit to reuse " syntax, i.e.

val x = "EOF
    one
    "two"
    """three"""
EOF
1 Like

A conservative approach would be to have a new stripping interpolator that:

val x = str”foo
           |bar
           |baz”

And deprecate the old one.

Using a custom interpolator is not good enough as I mentioned before: Multiline string literals: can we get rid of the need for stripMargin?

Hear, hear! or rather Here, here! for heredoc.

REPL lets you specify a margin character, by analogy to detabbing <<- or <<~ style.

scala> :paste <| EOF
// Entering paste mode (EOF to finish)

    |class C { def f = 42 }
EOF

// Exiting paste mode, now interpreting.

defined class C

Probably there would be more demand for this sort of thing, and uniformity across snippets, scripts, and so-called normal code, if Scala were used more in anger for “scaled” development. Right now, as per the other thread, my main snippet doesn’t scale from REPL to @main.

As for Scaladoc, we’d need to standardize the spelling of hereDoc. I’d be inclined to pronounce it like “heretic”, as it is a syntactic tic.

It’s clear heredoc syntax isn’t used in REPL because no one complains about it. I’d expect the first case to detect the desired indent.

scala> :pa <-
// Entering paste mode (ctrl-D to finish)

  val s = """
    hi
    world
  """

// Exiting paste mode, now interpreting.

s: String =
"
hi
world
"

scala> :pa <*
// Entering paste mode (ctrl-D to finish)

val s = """
  *  hi
  *  world
"""

// Exiting paste mode, now interpreting.

s: String =
"
  hi
  world
"

scala>

It’s encouraging that REPL already prints multiline singly-quoted strings.

The current limitation on interpolators excludes val s = <<EOF"my text... in some shoehorning of syntax. Reminder that the result can also take parameters, such as

val s = sm" * strip comment asterisk"("* ")

I haven’t read through all the comments, just wanted to mention that groovy has a stripIndent function. I did not have a look at their algorithm but maybe it is good enough (never had problems at least):

I see that you linked to a post that said it wasn’t optimal because you felt the default could do it, but I don’t see that it “is not good enough”. It is a fact of life to deal with deprecations. Adding a new interpolator and deprecating the old one seems “good enough” to me. Adding more syntax is a real cost.

The problem is that we want this behavior for all interpolators, not just one specific interpolator.