Recognizing the delimiter
The examples given in the question obscure an important mechanical detail relevant to Python's implementation (and possibly others). A Python raw string literal uses the same lexing/tokenization rule as other string literals: a string consists of sequences of (anything except the closing quote) or (a backslash followed by a single character). It only has different rules for interpreting that token (everything is treated literally, including backslashes).
This has two important consequences:
A Python raw string literal can including the closing quote character, but only immediately after a backslash (which the resulting string will contain literally).
A Python raw string literal cannot end with an odd number of backslash characters.
An alternative rule (apparently used in Go, as seen in bigyihsuan's answer) is to just lex the string a character at a time, looking for the closing quote mark. This has the consequence that the literal can't include the closing quote at all, but then backslashes behave completely normally and are easy to understand.
(The above description deliberately glosses over the complication introduced by Python's "triple-quoted" string literals.)
Making raw strings primary
Following the Pythonic principle that "explicit is better than implicit", one could imagine a language in which "raw" strings are the default while strings that use backslash escapes require some special markup (or even an explicit call to an unescaping function, which might be applied at compile-time). This is the approach I am taking in my own design.
With this approach, the standard unescaping scheme would still not be able to use \'
or \"
escapes (since they could not be present to begin with); but this is not strictly necessary anyway. There are already other commonly understood ways to escape these characters, e.g. with hex codes (\x22
for a double quote and \x27
for a single quote); or one can invent new ones (perhaps \q
for a single quote and \Q
for a double quote).
Making the unescaping process explicit also offers the opportunity to specify error handling (should a literal like '\c'
, where there is no such escape sequence, produce a string that actually has a backslash in it? Produce a string with only the c
? Raise an exception / cause a compilation error? Something else?).
Adding quotes
There are several possible workarounds for the inability to include the closing quote mark in such a raw string literal. Being able to choose between '
and "
delimiters is already helpful, of course. If a string needs to contain both, this can be handled by concatenation with another literal, which could be explicit (using whatever string concatenation operator) or implicit (like "a string with both '" ' and " in it'
). Another option is special rules for implicit concatenation - for example, it could be understood that implicit concatenation of two raw literals using the same quote type, like 'I' 'll'
, implicitly adds an intervening quote of that type (to make I'll
). This is, in effect, functionally equivalent to "escaping" that quote character by doubling it up (as seen in some CSV dialects).
In my design, raw literals with the same quote type are implicitly concatenated with that quote when they appear on the same line of the source file, and with a newline when they appear on consecutive lines. The latter makes it easy to write multi-line raw-literal text without needing to worry about leading indentation.
##"multiple hashes"##
like in Swift? $\endgroup$file_get_contents()
count? Not sure whether that's worth adding as an answer. $\endgroup$