I like the proposal to have these sort of raw strings, where indentations are removed, but can't they use a symbol before the string like they do with interpolation `$` or literals `@`?
I know it says design decision to go with 1 more " than the longest sequence of " in the string, but why ?
A design goal is that you won’t need to escape _any_ character sequence in the string. In your proposal, a " inside a literal string would have to be escaped.
In practice, using """ will be sufficient almost all the time.
It's more about not needing to escape characters than stripping indentation (that's just an extra perk). Otherwise, if the string can contain `"`, how can the compiler know which `"` defines the end of it?
R"SQL(my string without the sequence S Q L goes here)SQL"
You can use any extra delimiter you want. The concatenation rules make it easy for you to easily insert source code line breaks and indentation without literal string breaks or indentation.
We looked into this. However, there didn't seem to be any benefit to this above just the N-quote version (which fits into how C# does strings everywhere else). In the above case, the `SQL(` and `)SQL` tokens are just akin to N-quotes. Since there's no additional benefit, we went with the simpler approach that solves all these needs, but will look the same across all codebases.
Consistent use of language-specific tags makes it easier for tools to switch to a dedicated foreign-language parser when they encounter a tagged raw literal. The host language just provides the capability through arbitrary matchup, but its still up to users and tool authors to use them consistently. SQL is just one example. Embedded shader programs, XML (fragments), and Protobuf literals are other possibilities.
> but can't they use a symbol before the string like they do with interpolation `$` or literals `@`?
Hi! I'm the language designer here :)
I know it says design decision to go with 1 more " than the longest sequence of " in the string, but why ?
Because if we use a symbol before the string, then there needs to be some mechanism to escape it within the string. e.g. if you use `@` literals, you still need to escape quotes within the string literal. The point of this feature (which we try to spell out in the spec) is so that you can have content without the need to escape anything at all.
I always found these complex indentation-stripping rules to be confusing in a language such as Python. I was under the impression that C# doesn't treat whitespace significantly, so why do they need all these complex rules? Just interpret what's between the quotes literally.
When you have multiline strings, and don't want to start the lines with whitespace, it means you need to break the indentation of your code, which can look quite ugly. I'm not sure whether I want the compiler to do it like in the proposal though, I feel like it can easily cause unintentional issues.
I think breaking the indentation is the lesser of two evils, because it becomes very obvious what the content of the string is. I've never minded it too much personally in go, but I guess it's subjective.
Hi there! I'm the lang designer and i wrote up that spec. Could you clarify what you didn't understand about the indentation examples? I can work on clarifying them. Thanks!
You say "If the indentation behavior is not desired, it is also trivial to disable like so:"
And the code sample you show differs only in that closing quote isn't indented. You don't explain why and how that change would affect the generated string.
>And the code sample you show differs only in that closing quote isn't indented. You don't explain why and how that change would affect the generated string.
Hi there. This is explained in the spec in a few places. In the examples section it explicitly states:
> To make the text easy to read and allow for indentation that developers like in code, these string literals will naturally remove the indentation specified on the last line when producing the final literal value.
> If the indentation behavior is not desired, it is also trivial to disable like so:
I thought that was clear as the prior explanation says that we remove the indentation from teh last line. And then i show how you can disable it. Specifically, as you noted because the closing quote line is no longer indented. Cheers!
Interpolation is its own can of worms, but if you just want to be able to encode absolutely anything without escape characters, you just need two delimiters:
With all the hacks and exploits going on, and (Log4J) more security awareness coming,
I've been considering a safe String class that prevents some characters like CR,LF,\ that are seldom needed in business strings but used in system level things. Drawing a line between these two would increase security.
I think it's a good approach but I would do it the opposite way : create an UnsafeString and use that whenever your program takes external inputs. Then make it so that this UnsafeString can't be used directly but must always be consciously converted to (safe) String when using that data anywhere.
I have been temporarily working with c# for the past month after years of Go. It’s a different philosophy to Go, there is a lot of syntactic sugar and magic spells that make your life easy… but I don’t know if I prefer that to the Go way of doing things. I was pleasantly surprised tho. Much better experience than working with Java
I've had to go the other way around.. and I find Go extremely verbose compared to C# - as long as you're not forced to follow certain constraints (SonarCube-driven-development).
Its been fascinating seeing how many people who have not used C# much/in anger, write it off.
But also how common the theme is that once people use it a bit they are very pleasantly surprised.
This seems particularly endemic in the javascript crowd and its almost as if they have been brainwashed by too many kool aid blogs and don't have broad experience of having tried other technologies, but yet they are so self-assured.
I really don't understand why C# isn't used so much more widely in startups, and can only think it's a fashion and misplaced virtue signaling? Genuinely interested in opinions on this, what do you think?
Depends on the startup. The typical SV/consumer startups just don't know about it. More junior devs who don't have the corporate/enterprise experience or started learning with JS/frontend and haven't ventured out. Developers tend to choose what they know or what's popular, especially at a new organization, so the same tech stacks continue to dominate there.
I've built 3 adtech platforms with .NET and the productivity and performance has let us outcompete much bigger companies with a smaller team so it's fortunate for those who do know about it.
Modern Java has lots of improvements that have gone into it, and should not be too dissimilar from C#. For example, it already has multi-line strings, the same as the ones being proposed here.
Doesn't heredoc preserve the indentation unless you strip it back out ? I don't mean identation within the string, I mean level of indentation of where it is in the code
You can use it without indentication using <<- AND TAB (does not work with spaces, so copy and past won't work on hackernews - replace the spaces of the three content lines with a TAB):
Also, the Rust language itself only has one string type, str. std::string::String comes ultimately from Rust's alloc crate, it is special only in the limited sense that the prelude makes it available without specifically asking for it, but you could define your own prelude that introduces say MyText or CPlusPlusStyleString or whatever you wanted.
Admittedly having one string type is still more than C, or indeed C++ bother with but we might notice that those languages have a pretty terrible relationship with strings and suspect that's not a coincidence.
I hope it will also normalize newlines to `\n`. The current version of raw literals (@"...") just puts there whatever is in the file, so it in practice depends on if your program was compiled on Windows or Linux. Surely that should be irrelevant for the compilation to intermediate language
> Any line breaks within verbatim string literals are part of the resulting string. If the exact characters used to form line breaks are semantically relevant to an application, any tools that translate line breaks in source code to different formats (between "\n" and "\r\n", for example) will change application behavior.
Yes it does, but usually \n is committed in git, but on Windows it checks out as \r\n. So you are right that it technically does not depend on the system, but in practice there is a difference.
That's a very good point. Is it best practice to configure git to change line endings on Windows? I understand that these days Windows editors can handle unix line terminators corerctly.
We absolutely do not normalize newlines as that would defeat the purpose of raw literals. The point here is that your content is not interpreted as that's the pain area that people are hitting today. How you write your literal is what you get at the end of the day.
Note: if the content needs to be `\n` then just use that actual newline in teh code. WRT to the file line endings and whatnot, my recommendation is that you never use tools that arbitrarily change that behind your back as it does already have impact today in C#. For example, that will break standard `@""` strings today.
If your line endings are important, then your tools should be setup to respect what you wrote and not change them. All editors can be setup this way, as can git. And that would absolutely be my recommendation on how you should structure things for your code if newlines are relevant.
Are you left handed by any chance? Trying to resolve an argument about typos in right and left handed people, and I've noticed you have wrote "teh" in many comments (no judgement, you're doing God's work in my opinion). My theory is left handed people are more likely to press e faster than the right hand can get to t and h (in qwerty).
I've not kept up with C#, but does it have something akin to Rust's string continuation? In a Rust string literal a backslash followed by a newline causes the backslash and all following whitespace to be removed. So, for example:
let string = "foo\
bar";
Results in `string` having the contents "foobar". That would allow the user to specify the exact newline they need without depending on invisible characters remaining unchanged.
Nice, I'm surprized this is not already in the language. The only thing I find a bit strange is that the delimiters must be on separate lines (unless it is the special one-line-form). So this is apparantly not legal:
var s = """This is a
multiline string""";
Requiring the start and especially end quotes to be on a separate line makes it take a lot of vertical space. But OTOH, that is consistent with the default coding style in C# which is vertically verbose (with {} on lines by themselves).
> I'm surprized this is not already in the language.
Because it is already in the language.
var xml = @"
<element attr=""content"">
<body>
</body>
</element>";
This proposal mostly seems to be about some edge case where @" " syntax isn't good enough. But really, this whole thing is an improvement to an anti-pattern, and you should instead be looking into not needing multi-line block specific string literals in your code (e.g. putting templates in their own files/resources).
You've perfectly demonstrated one motivation for this proposal: your string literal is incorrect. Verbatim strings in C# require " to be escaped, your string should be:
var xml = @"
<element attr=""content"">
<body>
</body>
</element>";
All it perfectly demonstrates is that this is inherently an anti-pattern and that we're discussing features to work around things you shouldn't be doing to begin with.
If you want to store XML literals, then by all means do so, but within the code itself is inappropriate. Even the existing @" " syntax is a code-smell, the new syntax doesn't address why that is (e.g. validation/colorization/etc don't work for string literals containing arbitrary other languages).
.Net already has constructs to allow the dynamic creation of XML blocks (and JSON) without resorting to string-comcat shenanigans.
Anti-patterns are rarely as absolute as you're making this out to be. Sure, I agree, lots of times it's better to store xml or json literals not in code. But for something three lines long it's perfectly fine, more readable, and trivial. This new proposal makes it elegant to do so, the only issue is that the @"" syntax should never have been used and unfortunately now we are proposing a third string literal syntax. That I don't like.
18yrs of C# here and i say YES PLEASE to this feature. $@ does not cut work for this use-case and string processing has always been a performance bottleneck.
Times have changed, xml/web is becoming ubitiqos... espically in LOB apps where u can use WebView based frameworks to create cross-platform apps that share 99% of code.
Microsoft's "verbatim strings" aren't. Think of them instead as "Oops, we use a lot of backslashes here at Microsoft and over time that just looks more and more stupid" strings and then these actual raw strings make lots more sense than those did.
There's plenty of stuff in a middle ground where a separate template file is a waste. Your example, now that you've corrected it shows that nicely. A separate template would be a waste here for these few bytes, and yet "verbatim strings" mean instead of this just being some actual XML you can copy-paste it has to be escaped / unescaped.
If your issue is that you don't think string literals should be a thing at all, C# is the wrong language for you. Try one of the early numeric langauges, or something modern like WUFFS that eschews strings entirely because they're too dangerous. Once you accept that literals should be a thing (notice these aren't interpolated, they're just literals) this is an obvious idea.
The bad "verbatim" syntax should go away in favour of a raw literal syntax such as the one proposed here.
Thanks for chiming in, that makes sense! I probably would have put the prefix before the quotes, so it matches `@"..."` and the usage in C++ and Python. But there is probably a reason why that is not possible:
In place of all of the special rules for handling indentation, I wonder if they could simply define some extra starting chars (besides $$""" for controlling interpolation) to indicate suppress-leading-newline or suppress-ending-newline etc. Offhand this would seem more explicit than implicit, and be searchable (unlike a pattern).
Other than that, ++ for any mechanism to quote to arbitrary depth. I have imagined
No, although you're right, it doesn't look like they make it clear (although the example is in a little code element which presumably doesn't have leading or trailing newlines).
Later on,
> In the case of multi_line_raw_string_literal the initial whitespace* new_line and the final new_line whitespace* is not part of the value of the string.
Which I think says that the opening and closing new lines (after and before the """'s) are NOT part of the content of the string literal, but new lines between them can be part of the string literal.
Hi. I'm the designer of this lang feature. The specification covers this. However, to be clear, neither new line after the first `"""` is not part of the literal, nor is the newline before the last `"""`. Thanks!
As someone who has used C# since V1 beta, I would like to recommend slow down on the new features. They are adding weight to the tree and eventually it will fall over, or C# will become like C++ with too much complexity that limits usability and use.
Another comment here suggested just make a trivial way to reference an embedded text file resource, and that is already very possible and not hard already, as well as use of string Resources.
There are so many different ways to do strings in C#. Adding features like this just makes the language harder to learn, and the compiler harder to implement.
At this point, it's probably better to adjust the compiler to make it easier to turn a text file into a hardcoded string. The embedded resource approach works, but it could be significantly smoother.
Or, maybe the compiler needs some form of a plugin architecture so people who want obscure features can figure out how to add them?
Because it allows us to literally embed other languages within C# and provide full refactoring, tooling support. Next level stuff this (and something which should be normal, it's 2022 ffs!).
Hi. I'm the lang designer and feature implementor.
To your question of "why?", we tried to cover the reasoning in teh proposal. But, the core reason is that today people do use strings a ton. And in many cases it's unpleasant to do so because you always end up with reasons that you need to escape the content. This escaping serves to satisfy the compiler, but really doesn't buy value to teh user the majority of the time. The idea here is that you can just use a raw-string and say: here's the content, exactly as i want it.
> This allows code to look natural, while still producing literals that are desired, and avoiding runtime costs if this required the use of specialized string manipulation routines.
Maybe a source generator would be applicable here? Not as nice has having it built into the language of course, but it would at least eliminate these runtime costs.
I like the three-quote literal syntax in general, and am a bit surprised that C# doesn't have this already. Even Java has had this for awhile now!
But I don't like the indented form, where nested triple-quotes are ignored. Whitespace formatting is fine when I'm working with Python, but I really don't want to mix that paradigm when I'm working with curly-brace languages.
Nested triple-quotes are not ignored, they will end the string if you used triple to start. If you need to include triples quotes within the string, you start with quadruple.
If you wanted a newline at the end, you'd do this:
var xml = """<element attr="content">
""" <body>
""" </body>
"""</element>
"""
""";
Basically the end delimiter of the string would be the last """. You could concatenate two strings like so:
var xml = """<element attr="content">
""" <body>
""" </body>
"""</element>
"""
""" // this string ended on this line
+
"""<element attr="content">
""" <body>
""" </body>
"""</element>
"""
"""; // this string ended on this line
This could use the same logic for using at least three quotes as the indicator that it's a multiline string.
One benefit of multiline raw string is that you can directly copy/paste a block of characters between the program and its source. Unless there are very sophisticated IDE support this proposal does not work fine in this sense.
Ah, that's interesting. In general, yes my proposal does benefit from and assume some IDE/tooling support for quality of life.
Edit: To be specific, the IDE could handle formatting when pasting into a line beginning with """. Or offer a "paste as cool new multiline string syntax" feature.
I don't understand what problem this solves that the proposal in the linked article doesn't solve. Maybe you're not suggesting that it does, but then what's the upside?
Oh yeah, I was just sharing my string literal syntax that's been baking in my head for while for the sake of discussing.
But off the top of my head, mainly just that there's a clear visual indicator of the start of lines of text, rather than counting/lining up leading whitespace. In the first example, the strings are all tabbed evenly for the sake of looking "pretty" in the code, but the following would generate the same string, since each line begins after the """:
var xml = """<element attr="content">
""" <body>
""" </body>
"""</element>
""";
Hi. I'm the language designer behind this feature :)
A few points.
> but the following would generate the same string, since each line begins after the """:
That's not a virtue here. The point is to be able to write clear literals that never need escapes and which allow for easy grokking of what the content actually is.
All current string forms in C# require some amount of manual (or tooling) help to fix them up to be legal. That's not the case with this literal. The content can always work as-is without having to touch it at all.
That definitely makes sense. In my (limited, especially not C#) experience I just really dislike reasoning about trimming the leading whitespace, even if the rules are simple. I yearn for a consistent visual cue.
In my syntax, the IDE would ideally treat the """ block virtually like a <textarea>.
> I just really dislike reasoning about trimming the leading whitespace
Note: this feature is entirely optional. You can absolutely not have leading whitespace trimming at all. Indeed, this is a requirement of the proposal as we have to make it possible to actually represent text that has leading whitespace :)
Xtend is a programming language designed as a syntactic layer over Java (and transpiles to it), it was designed specifically for code generation for the Xtext framework. It has its own take on multi-line interpolation-equipped strings : template expression.
It has this idea called whitespace preprocessing, it has several rules but one of them guarantees that your first 2 examples would work as you intend them to.
Are those strings containing `"` and `""` or are they empty strings? Is the first case an error because the starting and ending quote counts do not match? If the number of quote chars is even, do the contents alternate between `"` and empty as the number of surrounding quotes increases?
> A single_line_raw_string_literal cannot represent a string value that starts or ends with a quote (") though an augmentation to this proposal is provided in the Drawbacks section that shows how that could be supported.
so I'd assume the odd count would lead to an error (single trailing "?) rather than a string containing ".
E: I'd assume it doesn't allow empty single line strings because otherwise how do you tell the difference between that and the start of a multi line one?
Hi there, I'm the lang designer and implementor here.
That would violate a core goal of the feature which is that the content itself doesn't need escaping. This sort of approach would require all users to have tooling that would make that pleasant, instead of providing a feature that was easy to use across any editor.
This means that a C# compiler can't start with a simple tokenizing loop. That compiler phase would have to keep track of state in a stack, recording what each } character means while its still looping through code character-by-character.
Now we're adding {{ and }} into the equation. Yay.
A simple loop that would have worked with the 70s era of programming languages, would go through each character and once the boundary between two tokens has been identified, write out a token to a one-dimensional list. This would be a mostly stateless loop, tracking enough state for the current token in hand only. The next phase would go through the tokens and pair up brackets, etc.
A C# tokenizer can't do that. It needs to keep a stack of state. When it sees a '}', it needs to know if that's a "normal" brace or the } that resumes a interpolated string literal.
I was writing a tokenizer myself and I wanted to have something similar to string interpolation. I very quickly realized my simple loop that I would have written for my CS degree isn't going to cut it and I had to start over.
Hi, I'm one of teh C# language designers, and I work on the compiler implementation as well.
C# has never had a "simple tokenizer". Indeed, even the first language has complex lexical constructs that are part and parcel of the language. For example, our comments can store structured data in them (like xml).
> A simple loop that would have worked with the 70s era of programming languages
Yes. But 70s era compilers had to deal with things like not having enough memory to even store basic amounts of data. It also had to work in spaces where things like a 'stack' was just not tenable. We're literally 50 years from that point, and having a compiler do stuff like keeping a stack is not an issue anymore :)
Then my compliments on your efforts. When I stumbled upon my own trouble writing a tokenizer, I wondered if the C# compiler had the same issue and maybe you couldn't have {} inside interpolated strings. I wrote my earlier expression with many nested {} expressions to see if your compiler would handle it and I was very happy to see it did.
Although you did deny me an excuse to not have to start over. If the C# team didn't bother, why should I? (Except you did bother.)
>Now we're adding {{ and }} into the equation. Yay.
Hi, i'm the lang designer and feature implementor here :)
The complexity of lexing/parsing did not get worse here. We actually just lex/parse this stuff the same way that interpolated strings have always been lexed/parsed. This has been supported in the language for almost 10 years at this point :)
I've long wanted a more succinct way of writing implicitly typed arrays. Whenever you work with data directly in the code, for example when hacking on leetcode, you end you with lots of horrible nested arrays:
To make the text easy to read and allow for indentation that developers like in code, these string literals will naturally remove the indentation specified on the last line when producing the final literal value.
This is the same rule that Oil has; I think it came from the Julia language (or at least that's where I got it from)
This is fantastic! After this is in, can anyone propose a better documentation syntax please? I am really tired of typing verbose XML as comments, and not even being able to write "a < b" or "T<int>" in my comments...
120 comments
[ 2.3 ms ] story [ 171 ms ] threadI like the proposal to have these sort of raw strings, where indentations are removed, but can't they use a symbol before the string like they do with interpolation `$` or literals `@`?
I know it says design decision to go with 1 more " than the longest sequence of " in the string, but why ?
I'd also much prefer some kind of prefix, maybe double "at", e.g.
``` var myString = @@"blah blah blah blah " ```
This feels a lot more natural to me.
In practice, using """ will be sufficient almost all the time.
> Provide a mechanism that will allow all string values to be provided by the user without the need for any escape-sequences whatsoever.
""" Is fine though.
We looked into this. However, there didn't seem to be any benefit to this above just the N-quote version (which fits into how C# does strings everywhere else). In the above case, the `SQL(` and `)SQL` tokens are just akin to N-quotes. Since there's no additional benefit, we went with the simpler approach that solves all these needs, but will look the same across all codebases.
Hi! I'm the language designer here :)
I know it says design decision to go with 1 more " than the longest sequence of " in the string, but why ?
Because if we use a symbol before the string, then there needs to be some mechanism to escape it within the string. e.g. if you use `@` literals, you still need to escape quotes within the string literal. The point of this feature (which we try to spell out in the spec) is so that you can have content without the need to escape anything at all.
It doesn't for code, it does for strings.
If you have:
That string is actually In raw string form, as per the proposal, the string would be: It allows you to write strings nicely inline, and the indentation in the string itself doesn't matter.And the code sample you show differs only in that closing quote isn't indented. You don't explain why and how that change would affect the generated string.
Each line in the literal will have leading whitespace trimmed off, up to where the closing quotes are.
(What happens if the closing quotes pass some of the text?)
That's an error. Called out here: https://github.com/dotnet/csharplang/blob/main/proposals/raw...
Hi there. This is explained in the spec in a few places. In the examples section it explicitly states:
> To make the text easy to read and allow for indentation that developers like in code, these string literals will naturally remove the indentation specified on the last line when producing the final literal value.
> If the indentation behavior is not desired, it is also trivial to disable like so:
I thought that was clear as the prior explanation says that we remove the indentation from teh last line. And then i show how you can disable it. Specifically, as you noted because the closing quote line is no longer indented. Cheers!
stringA may start and/or end with a single quote
stringB may start with a single quote and/or end with a double quote
stringC may start with a double quote and/or end with a single quote
stringD may start and/or end with a double quote
I've been considering a safe String class that prevents some characters like CR,LF,\ that are seldom needed in business strings but used in system level things. Drawing a line between these two would increase security.
I like the idea but really I want the type to capture unsafe/semi-safe/safe. Now the trick is, how expressive can the idea of semi-safe be?
https://www.joelonsoftware.com/2005/05/11/making-wrong-code-...
But also how common the theme is that once people use it a bit they are very pleasantly surprised.
This seems particularly endemic in the javascript crowd and its almost as if they have been brainwashed by too many kool aid blogs and don't have broad experience of having tried other technologies, but yet they are so self-assured.
I really don't understand why C# isn't used so much more widely in startups, and can only think it's a fashion and misplaced virtue signaling? Genuinely interested in opinions on this, what do you think?
I've built 3 adtech platforms with .NET and the productivity and performance has let us outcompete much bigger companies with a smaller team so it's fortunate for those who do know about it.
This is just some syntactic sugar for strings that contain escape codes. It's still just a 'string'.
Admittedly having one string type is still more than C, or indeed C++ bother with but we might notice that those languages have a pretty terrible relationship with strings and suspect that's not a coincidence.
https://github.com/dotnet/csharplang/blob/main/proposals/utf...
> Any line breaks within verbatim string literals are part of the resulting string. If the exact characters used to form line breaks are semantically relevant to an application, any tools that translate line breaks in source code to different formats (between "\n" and "\r\n", for example) will change application behavior.
https://docs.microsoft.com/en-us/dotnet/csharp/language-refe...
We absolutely do not normalize newlines as that would defeat the purpose of raw literals. The point here is that your content is not interpreted as that's the pain area that people are hitting today. How you write your literal is what you get at the end of the day.
Note: if the content needs to be `\n` then just use that actual newline in teh code. WRT to the file line endings and whatnot, my recommendation is that you never use tools that arbitrarily change that behind your back as it does already have impact today in C#. For example, that will break standard `@""` strings today.
If your line endings are important, then your tools should be setup to respect what you wrote and not change them. All editors can be setup this way, as can git. And that would absolutely be my recommendation on how you should structure things for your code if newlines are relevant.
Because it is already in the language.
This proposal mostly seems to be about some edge case where @" " syntax isn't good enough. But really, this whole thing is an improvement to an anti-pattern, and you should instead be looking into not needing multi-line block specific string literals in your code (e.g. putting templates in their own files/resources).If you want to store XML literals, then by all means do so, but within the code itself is inappropriate. Even the existing @" " syntax is a code-smell, the new syntax doesn't address why that is (e.g. validation/colorization/etc don't work for string literals containing arbitrary other languages).
.Net already has constructs to allow the dynamic creation of XML blocks (and JSON) without resorting to string-comcat shenanigans.
Times have changed, xml/web is becoming ubitiqos... espically in LOB apps where u can use WebView based frameworks to create cross-platform apps that share 99% of code.
There's plenty of stuff in a middle ground where a separate template file is a waste. Your example, now that you've corrected it shows that nicely. A separate template would be a waste here for these few bytes, and yet "verbatim strings" mean instead of this just being some actual XML you can copy-paste it has to be escaped / unescaped.
If your issue is that you don't think string literals should be a thing at all, C# is the wrong language for you. Try one of the early numeric langauges, or something modern like WUFFS that eschews strings entirely because they're too dangerous. Once you accept that literals should be a thing (notice these aren't interpolated, they're just literals) this is an obvious idea.
The bad "verbatim" syntax should go away in favour of a raw literal syntax such as the one proposed here.
```c# var s = """xml <Book><title/></Book> """; ```
and the like. Thanks!
Other than that, ++ for any mechanism to quote to arbitrary depth. I have imagined
[abcfoo[ ...anything but ]abcfoo]... ]abcfoo]
as another approach.
Are they?
[1]: https://cr.openjdk.java.net/~jlaskey/Strings/TextBlocksGuide...
[2]: https://cr.openjdk.java.net/~jlaskey/Strings/TextBlocksGuide...
Later on,
> In the case of multi_line_raw_string_literal the initial whitespace* new_line and the final new_line whitespace* is not part of the value of the string.
``` multi_line_raw_string_literal : raw_string_literal_delimiter whitespace* new_line (raw_content | new_line)* new_line whitespace* raw_string_literal_delimiter ; ```
Which I think says that the opening and closing new lines (after and before the """'s) are NOT part of the content of the string literal, but new lines between them can be part of the string literal.
Another comment here suggested just make a trivial way to reference an embedded text file resource, and that is already very possible and not hard already, as well as use of string Resources.
There are so many different ways to do strings in C#. Adding features like this just makes the language harder to learn, and the compiler harder to implement.
At this point, it's probably better to adjust the compiler to make it easier to turn a text file into a hardcoded string. The embedded resource approach works, but it could be significantly smoother.
Or, maybe the compiler needs some form of a plugin architecture so people who want obscure features can figure out how to add them?
To your question of "why?", we tried to cover the reasoning in teh proposal. But, the core reason is that today people do use strings a ton. And in many cases it's unpleasant to do so because you always end up with reasons that you need to escape the content. This escaping serves to satisfy the compiler, but really doesn't buy value to teh user the majority of the time. The idea here is that you can just use a raw-string and say: here's the content, exactly as i want it.
Maybe a source generator would be applicable here? Not as nice has having it built into the language of course, but it would at least eliminate these runtime costs.
But I don't like the indented form, where nested triple-quotes are ignored. Whitespace formatting is fine when I'm working with Python, but I really don't want to mix that paradigm when I'm working with curly-brace languages.
Please, tear this apart and offer improvements.
Edit: this is conceptually similar to Zig's multiline literal: https://ziglang.org/documentation/master/#Multiline-String-L...
Edit: To be specific, the IDE could handle formatting when pasting into a line beginning with """. Or offer a "paste as cool new multiline string syntax" feature.
But off the top of my head, mainly just that there's a clear visual indicator of the start of lines of text, rather than counting/lining up leading whitespace. In the first example, the strings are all tabbed evenly for the sake of looking "pretty" in the code, but the following would generate the same string, since each line begins after the """:
A few points.
> but the following would generate the same string, since each line begins after the """:
That's not a virtue here. The point is to be able to write clear literals that never need escapes and which allow for easy grokking of what the content actually is.
All current string forms in C# require some amount of manual (or tooling) help to fix them up to be legal. That's not the case with this literal. The content can always work as-is without having to touch it at all.
In my syntax, the IDE would ideally treat the """ block virtually like a <textarea>.
Note: this feature is entirely optional. You can absolutely not have leading whitespace trimming at all. Indeed, this is a requirement of the proposal as we have to make it possible to actually represent text that has leading whitespace :)
https://www.eclipse.org/xtend/documentation/203_xtend_expres...
It has this idea called whitespace preprocessing, it has several rules but one of them guarantees that your first 2 examples would work as you intend them to.
> A single_line_raw_string_literal cannot represent a string value that starts or ends with a quote (") though an augmentation to this proposal is provided in the Drawbacks section that shows how that could be supported.
so I'd assume the odd count would lead to an error (single trailing "?) rather than a string containing ".
E: I'd assume it doesn't allow empty single line strings because otherwise how do you tell the difference between that and the start of a multi line one?
That would violate a core goal of the feature which is that the content itself doesn't need escaping. This sort of approach would require all users to have tooling that would make that pleasant, instead of providing a feature that was easy to use across any editor.
Thanks!
This means that a C# compiler can't start with a simple tokenizing loop. That compiler phase would have to keep track of state in a stack, recording what each } character means while its still looping through code character-by-character.
Now we're adding {{ and }} into the equation. Yay.
Not true, it just means that the parts between double quotes aren't bunched into a single token.
To figure out how the compiler makes sense of this code, try
https://roslynquoter.azurewebsites.net/
You'll see how it tokenizes the string.
A simple loop that would have worked with the 70s era of programming languages, would go through each character and once the boundary between two tokens has been identified, write out a token to a one-dimensional list. This would be a mostly stateless loop, tracking enough state for the current token in hand only. The next phase would go through the tokens and pair up brackets, etc.
A C# tokenizer can't do that. It needs to keep a stack of state. When it sees a '}', it needs to know if that's a "normal" brace or the } that resumes a interpolated string literal.
I was writing a tokenizer myself and I wanted to have something similar to string interpolation. I very quickly realized my simple loop that I would have written for my CS degree isn't going to cut it and I had to start over.
C# has never had a "simple tokenizer". Indeed, even the first language has complex lexical constructs that are part and parcel of the language. For example, our comments can store structured data in them (like xml).
> A simple loop that would have worked with the 70s era of programming languages
Yes. But 70s era compilers had to deal with things like not having enough memory to even store basic amounts of data. It also had to work in spaces where things like a 'stack' was just not tenable. We're literally 50 years from that point, and having a compiler do stuff like keeping a stack is not an issue anymore :)
Although you did deny me an excuse to not have to start over. If the C# team didn't bother, why should I? (Except you did bother.)
Hi, i'm the lang designer and feature implementor here :)
The complexity of lexing/parsing did not get worse here. We actually just lex/parse this stuff the same way that interpolated strings have always been lexed/parsed. This has been supported in the language for almost 10 years at this point :)
new [] {new [] {1, 2}, new [] {3, 4}};
Something like:
@[ @[1, 2], @[3, 4] ]
Thanks!
This is the same rule that Oil has; I think it came from the Julia language (or at least that's where I got it from)
Oil Has Multi-line Commands and String Literals http://www.oilshell.org/blog/2021/09/multiline.html
When a language gets its fourth or fifth string literal syntax, its process is probably broken.