Does Roc have support for raw string literals? E.g. r#"..."#
in rust.
we have triple quoted strings, which I kinda assume should suffice in practice
that is, they suffice for the use case of wanting unescaped quotation marks in them :big_smile:
they still support string interpolation
which I assume shouldn't be a problem in practice?
but I guess it depends on what you're looking to do with them!
Cool, that works
do we handle indentation in those? python and elm don't and it's really annoying if you want one of those in a nested scope
basically, I would like indoc!
to be the default behavior
yeah:
» foo =
… """
… asdasda
… adsd
… """
… foo
"asdasda
adsd" : Str
ah, nice
yeah the rule is that in a multiline triple-quoted string, you have to indent the opening and closing """
delimiters at the same level of indentation, and then that indentation level is treated as the beginning of the line for all the lines in between the delimiters
that said, I just realized the above repl output is syntactically invalid, and it should actually have printed the result using triple-quoted strings! :big_smile:
like it should have printed:
"""
asdasda
adsd
""" : Str
I'll open an issue for it
https://github.com/roc-lang/roc/issues/3793
Richard Feldman said:
The issue says "foo\nbar"
(single-quoted) should be printed as:
"""
foo
bar
""" : Str
But "foo\nbar"
is just as syntactally incorrect as
"foo
bar" : Str
and the REPL should give you an "I cannot find the end of this block string" error, should it not?
Ayaz Hafiz said:
yeah:
» foo = … """ … asdasda … adsd … """ … foo "asdasda adsd" : Str
I assumed it would be just a formatting issue, but it seems to be a parsing issue. When you enter """foo\nbar"""
in the REPL, that is being parsed as a PlainLine
instead of a Block
. I checked out compiler/parse/src/string_literal.rs
, but could not see why this would happen.
This is right place in the code, where the parsing for any string literal happens, right?
@Joshua Warner
Ralf Engbers said:
and the REPL should give you an "I cannot find the end of this block string" error, should it not?
I think I misunderstood triple-quote strings (I always saw them as unescaped raw strings like in Kotlin). But still, if "foo\nbar"
is syntactically correct, should the REPL print "foo\nbar" : Str
or the multi-line triple-quoted string?
ah, I should have clarified! :sweat_smile:
yeah, the whole issue is that the repl should print the multi-line triple quoted string
both of these are syntactically valid:
"foo\nbar"
"""
foo
bar
"""
however, this is not syntactically valid:
"foo
bar"
so the issue is that the repl should print the triple-quoted version
I have this working by adjusting fmt_string_literal
in compiler/fmt/src/expr.rs
and changing
PlainLine(string) => buf.push_str_allow_spaces(string);
to
PlainLine(string) => {
let mut lines = string.split("\n");
// This match will either be (Some(first), None) for single line strings,
// or (Some(first), Some(second)) for multiline strings.
match (lines.next(), lines.next()) {
(Some(first), Some(second)) => {
buf.push_str("\"\"");
buf.newline();
for line in [first, second].into_iter().chain(lines) {
buf.push_str_allow_spaces(line);
buf.newline();
}
buf.push_str("\"\"");
}
_ => buf.push_str_allow_spaces(string),
}
}
However, this function is used in many places (well, format_with_options
is, which calls this one) and I am not sure this would make sense as a general change, or whether there is an easy way to make this change only for the REPL. Pointers and comments are very welcome! =)
Btw, to be consistent in the output, the REPL would turn "\n"
into two empty lines:
"""
""" : Str
One specific reason why I am not confident in this change: for this to work, we would need to remove debug_assert!(!self.beginning_of_line)
and debug_assert!(!s.ends_with(' '))
from push_str
and push_str_allow_spaces
, because those things can now happen in the REPL.
Taking another look, I think it works like this (and of course without removing the debug_asserts
). This is the PR. Always happy for feedback!
Having no option other than indoc!
as the multiline string behavior has been a bit annoying to me during advent of code so far. I'm writing tests for each day by copying the examples given in the prompt, like so: https://github.com/TAGraves/adventofcode2022/blob/main/day1.roc#L39-L57
The indoc!
behavior means I have to paste in the example input and then indent it, instead of being able to paste it in directly. And when I want to copy it to my day.txt file (so I can run and debug the application using roc run
instead of roc test
, I have to un-indent it after pasting it into the text file :sad:.
a feature I've had in the back of my mind for a few years is a way to say "import
this file as a Str
" or "import
this file as raw bytes"
would that address this use case?
the thing I don't like about allowing for arbitrarily-outdented strings is that it makes the source code harder to read later on, because some things are outdented totally differfently from everything else :sweat_smile:
the thing I don't like about allowing for arbitrarily-outdented strings is that it makes the source code harder to read later on, because some things are outdented totally differfently from everything else
Interesting! I've not personally found that to be the case, but looking at some examples I understand what you're saying.
I think importing files as strings and having roc format
fix incorrectly-indented multiline strings could both help (though this one might be tricky to infer the correct way to format it!), if we don't want to provide the option to opt out of indoc!
.
a feature I've had in the back of my mind for a few years is a way to say "
import
this file as aStr
" or "import
this file as raw bytes"
I like that idea a lot!
Last updated: Jul 06 2025 at 12:14 UTC