-
-
Notifications
You must be signed in to change notification settings - Fork 97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
String Interpolation #165
String Interpolation #165
Conversation
Did you consider @adamdruppe's proposal on this? tl;dr: custom tuple-like struct which allows functions to customize output (think writeln or SQL statements). |
@WalterBright is my understanding correct that this proposal only works for direct stdout but assigning to e.g. a string variable is not possible? |
I'm not so sure about that. I use format strings all the time, and almost never use anything but a literal. If it does become a serious problem, this could be supported:
But it doesn't really matter if interpolated strings don't fit every niche. They just have to fit the most used ones, as there's a fallback - use the current method. |
BTW, the goal for this design was to minimize the amount of typing a user has to do, and make it usable for printf as well as writef. |
cade2a6
to
63e99b1
Compare
Not specifically, though I knew people were working and thinking about it. Adam should do it as a proper DIP. I've amended the DIP to add references to Adam's and Jason's work. |
Thinking about this a bit more, the end result of an |
Yes, all of my mid size D applications do not directly write to stdout but uses library functions for e.g. adding colors. Also if you want to build an http server (http response body), string interpolation would be really useful. Also in other languages string interpolation is not limited to stdout(for the languages I am aware of). |
I think there's a misunderstanding here. None of this DIP restricts it to stdout. |
Yes, it was a misunderstanding. You may add an example (string variable assignment, string argument assignment) to this DIP to make it clear for other readers. Thanks. |
I don't understand how |
My related PR: dlang/dmd#7988 |
My comment here addresses my concerns with lowering interpolated strings to format string tuples. dlang/dmd#7988 (comment) Lowering the interpolated string to a tuple of strings and expressions seems more versatile. |
Pull 7988 mentions HTML generation as a use case for string interpolation, this article uses such vulnerability in Firefox. |
Tuple based interpolation can do HTML generation more sanely (though I think html strings are mistakes anyway, but that's another thing) because as tuples, the types are available and then the function could - in theory at least - do some introspection and proper encoding based on that information. but indeed i would be generally skeptical, just tuples with type information - like my proposal tweak talked about - makes it possible to actually do it right. |
This is false, the language could lower an interpreted string to a Phobos function that checks the format string at compile time. E.g. |
Did you look at how swift does string interpolation? The Wikipedia reference here points to a vastly simplified example for swift that doesn't meantion how it handles escaping much smoother than any system I've seen before. |
If the `Element` is: | ||
|
||
* `Character`, it is written to the output string. | ||
* `'%%'`, a '%' is written to the output string. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'%%'
, a '%' is written to the output string.
Shouldn't it better be that %% stays as a %% in the resulting format string. Or else one will need to put %%%% in the interpolated string to get a % in the result of the writef or the printf.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would you write a %
to the output otherwise?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If during transformation of the interpolated string the %% becomes a %, then the format string will contain an isolated % which is an error in a format string. A double percent in the interpolated string has to stay a double percent in the format string, or else you would have to put 4 % chars.
The transformation is
interpolated string => format string => output
Example:
writef(i"Percent %{d}value %%") becomes
writef("Percent %d %", value) which is an error (at least undefined behaviour for printf.
``` | ||
becomes: | ||
``` | ||
printf("I ate %s and %d totalling %s fruit.\n", apples, bananas, apples + bananas); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should they all be d
's?
The cases where interpolated strings are useful is when the string is long... and in my experience, where I often generate shim or binding functions, those strings are always synthesised. They're rarely literals... so this feature is absolutely something I've wanted for 10 years, but won't actually suit my one common use case.
|
I think the better way of interpolation rules would be:
e.g.: This would
|
The much better way of interpolation rules would be:
e.g.:
This would
|
Look at Swift! They looked at what other languages did and made something nicer. There is no special interpolated string: |
So how is formatting handled in swifts case? Formatting specifiers? |
Well they punted a bit on that I'm afraid, so people use function calls, operator overloading or string conversion operators. So here is a good opportunity to one up swift! |
I still say we should just do the tuple of structs thing. That's a very simple rule and by far the most flexible - it doesn't even have to yield strings! |
Why use It's very confusing to see something like |
Why the percent or dollar? - If the string is interpolated, then the parser should know that everything inside braces should be evaluated, so |
Having to double curly braces in an interpolated string would make it awkward to use for code generation. Curly braces work great for python because they don't use curly braces to delimit code blocks. I also hardly see dynamic code generation in python so it wouldn't matter anyway, however, in D, I think using string interpolation inside mixins would be a major use case. |
Why would you use the i-strings for code generation when you have q{} ones? I would also argue that code generation is not what typical D programmer does. - We need string interpolation for hundreds of other, different reasons. And if people still insist, then I would agree to use $ instead of % as $ is used in other languages and we are more familiar with that style. |
On Fri, Oct 18, 2019 at 05:41:09AM -0700, Dejan Lekic wrote:
Why would you use the i-strings for code generation when you have q{} ones?
Note that that one of the proposals also had `iq{}` strings to
combine both.
|
I think we should have a survey here asking D developers on the forum to participate and tell us how often they generate complex blocks of D code. - Yes I am aware of the fact that developers want string mixins but the real question is how often people do this compared to the "regular" use-case when you just want to output some meaning text... I see people constantly talking about D being easy to prototype stuff, and for this to be true - easy, simple string interpolation without the need for some extra special characters to type all the time (% or $) is very much needed. |
@dejlek I implemented interpolated strings in this PR dlang/dmd#7988 and in the description I show an example of how it can be used in code generation. string generateFunction(string attributes, string returnType, string name, string args, string body)
{
import std.conv : text;
return text(iq{
$(attributes) $(returnType) $(name)($(args))
{
$(body)
}
});
}
mixin(generateFunction("pragma(inline)", "int", "add", "int a, int b", "return a + b;"));
assert(100 == add(25, 75)); Without interpolated strings, you can't insert dynamic content in the middle of a Here's a real example that is in phobos as well: https://github.com/marler8997/interpolated_strings/blob/master/phobos_example.d |
Might I suggest consideration to how C# does its string interpolation. It ends up being very clean and very quick to write.
|
string name;
string sentence = si"My name is ${name}"; si = string Interpolation |
Honestly, I like the way Python 3 formatted strings work: print(f"You have {value} apples. And all fruits: {apples + bananas}. A type / format can be specified too: {s:10s}, {sqrt(value):.3f}.") (Note that this is also very similar to C#, with a difference that format specifiers at the end are specified differently). (Programming language Nim, also uses this syntax, with almost exactly same syntax, modifiers, formatters and other details, like Python). And my favourite new form from Python 3.9 for debugging and quick value / expression dumps: print(f"Debugging some values: {a+b=}") Will for example display, Honestly, there is no need for special characters like |
@baryluk the python way has to have two escaping methods. And you can't escape from them. It's not very powerful and a big mess. Compare to swift which had one single special character |
What do you mean? It is easy and clear to use. Never had issues with escaping in Python. |
@baryluk it's clear. Sure. But easy? Or good? More doubtful. R-strings exist because you want to escape from the escaping. But there is no such thing for f strings. |
I really don't understand why we should use a character to specify that the string needs format and why we should put a special character before the format. The most logic way to do it as like that:
This is super simple and readable. Just add a curly bracket in the string and put the expression there. And of course we can use "{" to escape a bracket. I don't get why we must complicate things... |
@Godnyx You just complicated things. If your suggestion was implemented old code would break. And you'd have two escape characters: As opposed to in Swift where there's just one escape character: |
Yeah that would break tons of normal strings. |
After a bit of consideration and reading various DIPs and proposals on this topic, I agree now that both |
No description provided.