digitalmars.D - Just another example of missing string interpolation
- Andrea Fontana (18/18) Oct 12 2023 Real life example. Render a string like this:
- Imperatorn (4/22) Oct 12 2023 Agreed, as someone who uses C# every day, string interpolation is
- bachmeier (26/44) Oct 12 2023 I agree that string interpolation needs to be added to the
- Commander Zot (33/85) Oct 12 2023 or like this:
- bachmeier (15/48) Oct 12 2023 I had something like that but moved away from it. The version I
- kdevel (6/8) Oct 12 2023 What about
- Commander Zot (4/13) Oct 13 2023 my code was just an example, you'd have to properly do the
- kdevel (2/11) Oct 12 2023 What if `s` is `"${a}"` and `subs` is `["a": "${b}", "b": "x"]`?
- bachmeier (10/22) Oct 12 2023 That's the reason it needs to be supported by the language.
- kdevel (7/11) Oct 13 2023 The problem with your code is that it loops over the wrong list.
- bachmeier (6/15) Oct 13 2023 That depends. If you don't want to do all of the substitutions,
- bachmeier (16/33) Oct 13 2023 An example of a pattern I sometimes use:
- kdevel (12/30) Oct 13 2023 At which position? Which pseudo-variable is substituted in `s`?
- kdevel (13/28) Oct 13 2023 You don't have to do all substitutions in one go. If a key is
- bachmeier (4/13) Oct 13 2023 I don't know, but I also don't know why I would want to, because
- kdevel (4/9) Oct 13 2023 Maybe I misunderstood you in "Again, though, this really should
- Adam D Ruppe (4/6) Oct 13 2023 dip 1027 was utter trash, but there's future good dips that would
- Imperatorn (5/11) Oct 13 2023 We just want to be able to do
- Commander Zot (2/14) Oct 14 2023 yes. this would break existing code.
- Imperatorn (2/19) Oct 14 2023 Not with an interpolation character like $ in C#
- Andrey Zherikov (6/18) Oct 14 2023 Why does not this work for you?
- mw (9/30) Oct 14 2023 Too many unnecessary quotes and commas, tedious to write and
- Imperatorn (3/24) Oct 14 2023 It's ok, but just nicer to do it as in C#
- bachmeier (11/16) Oct 14 2023 We had a discussion on this a few years ago where someone said
- Andrea Fontana (3/8) Oct 14 2023 Check the first post.
- Imperatorn (5/14) Oct 15 2023 I would actually be fine with smith like
- Imperatorn (2/18) Oct 15 2023 Typo but you get the point 😅
- Andrea Fontana (10/30) Oct 15 2023 Yes these versions are fine too
- Imperatorn (2/28) Oct 15 2023 Agreed!
- Walter Bright (2/3) Oct 17 2023 Criticize ideas, not people. Personal attacks are not welcome here.
- mw (12/29) Oct 12 2023 There are library solutions, e.g shameless self-plug:
- mw (6/42) Oct 12 2023 The package is called: Just-Do-It
- Andrey Zherikov (24/42) Oct 12 2023 If you are using `write*` then you can simply do this:
- kdevel (18/24) Oct 13 2023 Where is the specific problem?
- Walter Bright (1/1) Oct 17 2023 https://github.com/dlang/DIPs/blob/master/DIPs/rejected/DIP1027.md
- Walter Bright (8/12) Oct 17 2023 With DIP1027:
- Walter Bright (6/10) Oct 17 2023 Oops, forgot the leading 'i':
- Adam D Ruppe (8/13) Oct 17 2023 Still won't work. Your dip1027 would write
- Walter Bright (2/15) Oct 17 2023 That's a misunderstanding of how it works.
- Adam D Ruppe (9/10) Oct 17 2023 No, that's exactly how it works. Read the document:
- Walter Bright (2/4) Oct 17 2023 Yes, it means I forgot to use writef instead of write.
- jmh530 (3/7) Oct 17 2023 Your version left off the format specifiers, but I don't think
- Walter Bright (2/6) Oct 17 2023 The %s format specifiers are inserted by default.
- Adam D Ruppe (5/6) Oct 17 2023 And the compiler wouldn't have told you about this. This is one
- Walter Bright (5/9) Oct 17 2023 Neither would YAIDIP. write() takes a variadic argument list.
- Adam D Ruppe (7/10) Oct 17 2023 Which is irrelevant because it *works correctly* when passed to
- Adam D Ruppe (8/9) Oct 17 2023 Actually, looking again, it states:
- Walter Bright (2/14) Oct 17 2023 How does the user specify the fully-qualified name of a compiler generat...
- Walter Bright (7/17) Oct 17 2023 I don't see how, from my reading of the proposal.
- Adam D Ruppe (20/24) Oct 17 2023 The first example under the Description shows this exact
- Walter Bright (15/31) Oct 17 2023 The line in question:
- Alexandru Ermicioi (17/35) Oct 18 2023 __header is implicitly converted to null string by writeln (the
- Walter Bright (3/6) Oct 18 2023 Ok. So does the user have to define his own InterpolatedExpression to ge...
- Adam D Ruppe (27/31) Oct 18 2023 "The __header value, to be discussed later, is generated by the
- Walter Bright (12/38) Oct 18 2023 Ok.
- Adam D Ruppe (67/80) Oct 18 2023 The types are attached to the parameters themselves, so it is
- Walter Bright (53/80) Oct 20 2023 Thanks for the example. I thought I'd show the equivalent with DIP1027. ...
- Imperatorn (11/69) Oct 20 2023 Whatever happens, can we please either merge the new dip or your
- Max Samukha (8/11) Oct 20 2023 This requires cumbersome workarounds for the format string to be
- Imperatorn (3/15) Oct 20 2023 I didn't know about that old "'static' function parameters", what
- Max Samukha (2/4) Oct 20 2023 `void foo(static T t);`
- Steven Schveighoffer (29/38) Oct 20 2023 If this is supposed to be a favorable comparison of 1027, this
- Imperatorn (5/9) Oct 20 2023 I'm just happy that I now can do this
- Imperatorn (2/13) Oct 20 2023 Just look at this. You know you want it 😅
- Daniel N (2/18) Oct 20 2023 LGTM merge... (if I could :p)
- Imperatorn (3/10) Oct 20 2023 Hehe, I posted some instructions here if you want to try it out:
- Commander Zot (9/40) Oct 20 2023 thank you.
- Paul Backus (18/22) Oct 20 2023 Because templates are lexically scoped, the body of the `i`
- Steven Schveighoffer (61/65) Oct 20 2023 I misspoke, 1027 doesn't actually handle `printf` very well, you
- Andrea Fontana (11/15) Oct 18 2023 The DIP linked by Adam is very appealing to me. All the modern
- Bradley Chatha (26/28) Oct 18 2023 Because the parts of the D community that are both vocal and
- Walter Bright (8/12) Oct 18 2023 Example of the complexity? It's probably the simplest string interpolati...
- Andrea Fontana (12/21) Oct 19 2023 For example:
- Walter Bright (6/12) Oct 19 2023 The error won't result in anything other than oops there's a format stri...
- Andrea Fontana (16/30) Oct 19 2023 Not by mistake, but intentionally because I want to pass a
- Richard (Rikki) Andrew Cattermole (5/5) Oct 19 2023 As long as the literal cannot expand out into regular strings and only
- Andrea Fontana (5/11) Oct 19 2023 But walter's proposal expands it to a tuple if I understand it
- Richard (Rikki) Andrew Cattermole (3/3) Oct 19 2023 Don't worry about it, it has already been rejected and this was one of
- Daniel N (9/12) Oct 19 2023 I think the simplest solution is to give up on one-size-fits-all.
- claptrap (3/6) Oct 19 2023 I don't think Walter has given up on it :P
- Walter Bright (2/6) Oct 19 2023 It doesn't give that as a reason.
- Walter Bright (7/10) Oct 19 2023 It will be:
- Steven Schveighoffer (11/22) Oct 19 2023 You might get a message like:
- Walter Bright (24/26) Oct 20 2023 I don't recall this issue even being discussed in the old review of it. ...
- Imperatorn (3/9) Oct 20 2023 What are your main objections to this
- Imperatorn (6/17) Oct 20 2023 It looks like a good DIP, and as a plus it has an implementation:
- Steven Schveighoffer (28/47) Oct 20 2023 No it's not listed (which surprises me), and the thread is huge,
- Walter Bright (9/14) Oct 20 2023 You'll get an exception message:
- Steven Schveighoffer (12/26) Oct 20 2023 So you think it's a nothingburger to have zero idea where this
- max haughton (3/12) Oct 20 2023 This feels like the kind of thing that "Make illegal states
- H. S. Teoh (8/10) Oct 17 2023 Just read through this. This is one of the better interpolated string
- Adam D Ruppe (15/19) Oct 17 2023 Yeah, this proposal is actually just plain excellent, and the
- Richard (Rikki) Andrew Cattermole (13/13) Oct 17 2023 I decided to have a go and do my own little proposal. Its a pretty big
- Imperatorn (6/24) Oct 17 2023 Just a quick comment. Probably with string interpolation, less is
- Walter Bright (5/6) Oct 18 2023 Solving for 90% of the cases with a simple solution is preferable than a...
- monkyyy (4/13) Oct 18 2023 hmmmmm
- Walter Bright (3/5) Oct 19 2023 For another example, the iphone camera pretty much destroyed the market ...
- monkyyy (11/17) Oct 19 2023 I didn't misunderstand you I disagree with your numbers and what
- Adam D Ruppe (4/7) Oct 18 2023 YAIDIP is an incredibly simple solution that has enormous bang
- Bruce Carneal (5/13) Oct 19 2023 I like YAIDIP a lot from what I've read. I also trust Adam and
- Imperatorn (2/11) Oct 18 2023 Agreed
- Imperatorn (3/12) Oct 19 2023 Please give us something, anything at all 😭
Real life example. Render a string like this: ``` \x1b[2K\r\x1b[1mProgress:\x1b[0m 50% \x1b[1m\tSpeed:\x1b[0m 15.5 KB/s ``` now (error prone and difficult to debug, try to code it!): ``` stderr.write(format("%s\r%sProgress:%s %5.1f%% %s\tSpeed:%s %6.1f %s%s", clear, white, clear, progress, white, clear, curSpeed, unit)); ``` (or with string concat, good luck!) vs: ``` stderr.write("${clear}\r{$white}Progress:${clear}${progress}% \t${white}Speed:${clear} ${curSpeed} ${unit}"); ``` Andrea
Oct 12 2023
On Thursday, 12 October 2023 at 13:39:46 UTC, Andrea Fontana wrote:Real life example. Render a string like this: ``` \x1b[2K\r\x1b[1mProgress:\x1b[0m 50% \x1b[1m\tSpeed:\x1b[0m 15.5 KB/s ``` now (error prone and difficult to debug, try to code it!): ``` stderr.write(format("%s\r%sProgress:%s %5.1f%% %s\tSpeed:%s %6.1f %s%s", clear, white, clear, progress, white, clear, curSpeed, unit)); ``` (or with string concat, good luck!) vs: ``` stderr.write("${clear}\r{$white}Progress:${clear}${progress}% \t${white}Speed:${clear} ${curSpeed} ${unit}"); ``` Andrealike the most used feature lol
Oct 12 2023
On Thursday, 12 October 2023 at 13:39:46 UTC, Andrea Fontana wrote:Real life example. Render a string like this: ``` \x1b[2K\r\x1b[1mProgress:\x1b[0m 50% \x1b[1m\tSpeed:\x1b[0m 15.5 KB/s ``` now (error prone and difficult to debug, try to code it!): ``` stderr.write(format("%s\r%sProgress:%s %5.1f%% %s\tSpeed:%s %6.1f %s%s", clear, white, clear, progress, white, clear, curSpeed, unit)); ``` (or with string concat, good luck!) vs: ``` stderr.write("${clear}\r{$white}Progress:${clear}${progress}% \t${white}Speed:${clear} ${curSpeed} ${unit}"); ``` AndreaI agree that string interpolation needs to be added to the language (it's 2023) but for the benefit of an outsider reading your message, there are better options than calling `format`. I use a generalization of this: ``` string interp(string s, string[string] subs) { foreach(k; subs.keys) { s = s.replace("${" ~ k ~ "}", subs[k]); } return s; } ``` For your example, I'd call this ``` std.file.write("foo.txt", interp("${clear}2K\r${white}Progress:${clear}${progress}% \t${white}Speed:${clear} ${curSpeed} ${unit}", ["clear": "\x1b[", "white": "\x1b[1m", "progress": "0m 50", "curSpeed": "0m 15.5", "unit": "KB/s"])); ``` Would be much better to have this in the language, so I wouldn't have to specify all the substitutions, but a lot better than using `format` IMO.
Oct 12 2023
On Thursday, 12 October 2023 at 16:31:39 UTC, bachmeier wrote:On Thursday, 12 October 2023 at 13:39:46 UTC, Andrea Fontana wrote:or like this: ``` string enableInterpolation() { return q{ string interp(string s)() { import std.algorithm; import std.meta; import std.array; import std.conv; import std.functional; enum spl = aliasSeqOf!(s.splitter(" ").array) ; template P(string e) { static if(e.startsWith("$")) { mixin("enum P = ()=>"~e[1..$]~".to!string;"); } else { string fn(){ return e;} enum P = &fn; } } return [staticMap!(P, spl)].map!(f=>f()).join(" "); } }; } int main() { import std.stdio; float speed = 42; mixin(enableInterpolation()); writeln(interp!"i has $speed !"); return 0; } ```Real life example. Render a string like this: ``` \x1b[2K\r\x1b[1mProgress:\x1b[0m 50% \x1b[1m\tSpeed:\x1b[0m 15.5 KB/s ``` now (error prone and difficult to debug, try to code it!): ``` stderr.write(format("%s\r%sProgress:%s %5.1f%% %s\tSpeed:%s %6.1f %s%s", clear, white, clear, progress, white, clear, curSpeed, unit)); ``` (or with string concat, good luck!) vs: ``` stderr.write("${clear}\r{$white}Progress:${clear}${progress}% \t${white}Speed:${clear} ${curSpeed} ${unit}"); ``` AndreaI agree that string interpolation needs to be added to the language (it's 2023) but for the benefit of an outsider reading your message, there are better options than calling `format`. I use a generalization of this: ``` string interp(string s, string[string] subs) { foreach(k; subs.keys) { s = s.replace("${" ~ k ~ "}", subs[k]); } return s; } ``` For your example, I'd call this ``` std.file.write("foo.txt", interp("${clear}2K\r${white}Progress:${clear}${progress}% \t${white}Speed:${clear} ${curSpeed} ${unit}", ["clear": "\x1b[", "white": "\x1b[1m", "progress": "0m 50", "curSpeed": "0m 15.5", "unit": "KB/s"])); ``` Would be much better to have this in the language, so I wouldn't have to specify all the substitutions, but a lot better than using `format` IMO.
Oct 12 2023
On Thursday, 12 October 2023 at 17:25:09 UTC, Commander Zot wrote:or like this: ``` string enableInterpolation() { return q{ string interp(string s)() { import std.algorithm; import std.meta; import std.array; import std.conv; import std.functional; enum spl = aliasSeqOf!(s.splitter(" ").array) ; template P(string e) { static if(e.startsWith("$")) { mixin("enum P = ()=>"~e[1..$]~".to!string;"); } else { string fn(){ return e;} enum P = &fn; } } return [staticMap!(P, spl)].map!(f=>f()).join(" "); } }; } int main() { import std.stdio; float speed = 42; mixin(enableInterpolation()); writeln(interp!"i has $speed !"); return 0; } ```I had something like that but moved away from it. The version I posted works better if I want to transform some of the variables. If I do that in a mixin, I have to parse the input. I actually do something like this using a struct: ``` string s = "String needing interpolation to insert ${y} and ${x}."; Subs subs; subs["y"] = str.split("/")[0]; subs["x"] = 2.6*j; interp(s, subs); ``` Again, though, this really should be done by the language rather than the user having to mess with it.
Oct 12 2023
On Thursday, 12 October 2023 at 17:25:09 UTC, Commander Zot wrote:[...] writeln(interp!"i has $speed !");What about ```d writeln(interp!"i has $speed,$speed !"); ``` ?
Oct 12 2023
On Thursday, 12 October 2023 at 19:56:48 UTC, kdevel wrote:On Thursday, 12 October 2023 at 17:25:09 UTC, Commander Zot wrote:my code was just an example, you'd have to properly do the parsing of the string. but there are already packages on dub for that[...] writeln(interp!"i has $speed !");What about ```d writeln(interp!"i has $speed,$speed !"); ``` ?
Oct 13 2023
On Thursday, 12 October 2023 at 16:31:39 UTC, bachmeier wrote:[...] I use a generalization of this: ``` string interp(string s, string[string] subs) { foreach(k; subs.keys) { s = s.replace("${" ~ k ~ "}", subs[k]); } return s; } ```What if `s` is `"${a}"` and `subs` is `["a": "${b}", "b": "x"]`?
Oct 12 2023
On Thursday, 12 October 2023 at 19:42:41 UTC, kdevel wrote:On Thursday, 12 October 2023 at 16:31:39 UTC, bachmeier wrote:That's the reason it needs to be supported by the language. What I do in practice is replace `${` in `subs[k]` with `ControlChar.us`, then convert `ControlChar.us` to `$` before returning the final result. That's because I would never have `ControlChar.us` in a string with interpolation, and I don't have to worry about efficiency because it's just not an issue. Your example is something I don't have to worry about very often. This is in no way a solution that would be suitable for the compiler or Phobos. It's a hack that works for me.[...] I use a generalization of this: ``` string interp(string s, string[string] subs) { foreach(k; subs.keys) { s = s.replace("${" ~ k ~ "}", subs[k]); } return s; } ```What if `s` is `"${a}"` and `subs` is `["a": "${b}", "b": "x"]`?
Oct 12 2023
On Thursday, 12 October 2023 at 21:45:55 UTC, bachmeier wrote:The problem with your code is that it loops over the wrong list. It should iterate over the variable occurrences in the string `s`. Granted that the language does support interpolation (DIP 1027): How would you implement your function string interp(string s, string[string] subs) in terms of that built-in interpolation?[...] What if `s` is `"${a}"` and `subs` is `["a": "${b}", "b": "x"]`?That's the reason it needs to be supported by the language.
Oct 13 2023
On Friday, 13 October 2023 at 12:04:18 UTC, kdevel wrote:On Thursday, 12 October 2023 at 21:45:55 UTC, bachmeier wrote:That depends. If you don't want to do all of the substitutions, either because you potentially have `${something}` as part of the final string, or because you don't want to do all substitutions at once, those cases are trivially handled by my function. It works for what I do.The problem with your code is that it loops over the wrong list. It should iterate over the variable occurrences in the string `s`.[...] What if `s` is `"${a}"` and `subs` is `["a": "${b}", "b": "x"]`?That's the reason it needs to be supported by the language.
Oct 13 2023
On Friday, 13 October 2023 at 14:25:34 UTC, bachmeier wrote:On Friday, 13 October 2023 at 12:04:18 UTC, kdevel wrote:An example of a pattern I sometimes use: ``` string foo(string s) { // Do a computation and substitute the result into s // return the new s } string bar(string s) { // Do a computation and substitute the result into s // return the new s } string s = "String needing interpolation to insert ${y} and ${x}."; string s2 = foo(s); string s3 = bar(s2); ```On Thursday, 12 October 2023 at 21:45:55 UTC, bachmeier wrote:That depends. If you don't want to do all of the substitutions, either because you potentially have `${something}` as part of the final string, or because you don't want to do all substitutions at once, those cases are trivially handled by my function. It works for what I do.The problem with your code is that it loops over the wrong list. It should iterate over the variable occurrences in the string `s`.[...] What if `s` is `"${a}"` and `subs` is `["a": "${b}", "b": "x"]`?That's the reason it needs to be supported by the language.
Oct 13 2023
On Friday, 13 October 2023 at 14:31:01 UTC, bachmeier wrote:[...] An example of a pattern I sometimes use: ``` string foo(string s) { // Do a computation and substitute the result into s // return the new s ```At which position? Which pseudo-variable is substituted in `s`? Your functions `foo` and `bar` both not only make calls to `interp` but they also necessarily contain, in order to succeed, the name of the variable.``` } string bar(string s) { // Do a computation and substitute the result into s // return the new s } string s = "String needing interpolation to insert ${y} and ${x}."; string s2 = foo(s); string s3 = bar(s2); ```Your approach creates more dependencies between unrelated components than necessary. How do you unittest `foo` and `bar`? The dependencies can easily be avoided if `foo` and `bar` only returned the value of the computation, the results are stored in the AA given as `subs` in the call to `interp`.
Oct 13 2023
On Friday, 13 October 2023 at 15:34:59 UTC, kdevel wrote:Your functions `foo` and `bar` both not only make calls to `interp` but they also necessarily contain, in order to succeed, the name of the variable.YesYour approach creates more dependencies between unrelated components than necessary.Then don't use it? The goal of programming is to get the right output.How do you unittest `foo` and `bar`?The same as any other function.The dependencies can easily be avoided if `foo` and `bar` only returned the value of the computation, the results are stored in the AA given as `subs` in the call to `interp`.I prefer less complicated code to code that imposes arbitrary restrictions.
Oct 13 2023
On Friday, 13 October 2023 at 17:38:23 UTC, bachmeier wrote:On Friday, 13 October 2023 at 15:34:59 UTC, kdevel wrote:But then you can't re-use `foo` with another string, e.g. "String needing interpolation to insert ${yold} and ${ynew}."Your functions `foo` and `bar` both not only make calls to `interp` but they also necessarily contain, in order to succeed, the name of the variable.YesYour code does not meet that requirement.Your approach creates more dependencies between unrelated components than necessary.Then don't use it? The goal of programming is to get the right output.Having the signature of `foo` and `bar` alone I am not able to write a unittest.How do you unittest `foo` and `bar`?The same as any other function.In your code of `foo` and `bar` you have to assemble the AA and call `interp` twice compared to once. I would call my approach less complicated and my `foo` and `bar` versions do not suffer from the arbitrary restriction of beeing applicable only to strings having a predefined variable name.The dependencies can easily be avoided if `foo` and `bar` only returned the value of the computation, the results are stored in the AA given as `subs` in the call to `interp`.I prefer less complicated code to code that imposes arbitrary restrictions.
Oct 13 2023
On Friday, 13 October 2023 at 14:25:34 UTC, bachmeier wrote:On Friday, 13 October 2023 at 12:04:18 UTC, kdevel wrote:You don't have to do all substitutions in one go. If a key is missing in `subs` one alternative to throwing `MissingKey` could be to silently skip that variable occurrence.On Thursday, 12 October 2023 at 21:45:55 UTC, bachmeier wrote:That depends. If you don't want to do all of the substitutions,The problem with your code is that it loops over the wrong list. It should iterate over the variable occurrences in the string `s`.[...] What if `s` is `"${a}"` and `subs` is `["a": "${b}", "b": "x"]`?That's the reason it needs to be supported by the language.either because you potentially have `${something}` as part of the final string,How do you convey that intent inside the string? `format` does it by estabilishing a special syntax for `%` (`%%` -> `%`). How do you handle that case with DIP 1027? And reminder: How do you implement your `interp` function in terms of DIP 1027's string interpolation?
Oct 13 2023
On Friday, 13 October 2023 at 15:16:27 UTC, kdevel wrote:I don't need to.either because you potentially have `${something}` as part of the final string,How do you convey that intent inside the string? `format` does it by estabilishing a special syntax for `%` (`%%` -> `%`).How do you handle that case with DIP 1027? And reminder: How do you implement your `interp` function in terms of DIP 1027's string interpolation?I don't know, but I also don't know why I would want to, because DIP 1027 was not accepted.
Oct 13 2023
On Friday, 13 October 2023 at 17:31:29 UTC, bachmeier wrote:Maybe I misunderstood you in "Again, though, this really should be done by the language rather than the user having to mess with it."And reminder: How do you implement your `interp` function in terms of DIP 1027's string interpolation?I don't know, but I also don't know why I would want to, because DIP 1027 was not accepted.
Oct 13 2023
On Friday, 13 October 2023 at 17:31:29 UTC, bachmeier wrote:I don't know, but I also don't know why I would want to, because DIP 1027 was not accepted.dip 1027 was utter trash, but there's future good dips that would easily solve these things. pity D's leadership is so clueless and obstinate.
Oct 13 2023
On Friday, 13 October 2023 at 18:24:08 UTC, Adam D Ruppe wrote:On Friday, 13 October 2023 at 17:31:29 UTC, bachmeier wrote:We just want to be able to do string s = "Hello {name}, you are {age} years old and have {money - 42} dollars in the bank"; Is it too much to ask? 😭I don't know, but I also don't know why I would want to, because DIP 1027 was not accepted.dip 1027 was utter trash, but there's future good dips that would easily solve these things. pity D's leadership is so clueless and obstinate.
Oct 13 2023
On Saturday, 14 October 2023 at 06:25:15 UTC, Imperatorn wrote:On Friday, 13 October 2023 at 18:24:08 UTC, Adam D Ruppe wrote:yes. this would break existing code.On Friday, 13 October 2023 at 17:31:29 UTC, bachmeier wrote:We just want to be able to do string s = "Hello {name}, you are {age} years old and have {money - 42} dollars in the bank"; Is it too much to ask? 😭I don't know, but I also don't know why I would want to, because DIP 1027 was not accepted.dip 1027 was utter trash, but there's future good dips that would easily solve these things. pity D's leadership is so clueless and obstinate.
Oct 14 2023
On Saturday, 14 October 2023 at 11:31:53 UTC, Commander Zot wrote:On Saturday, 14 October 2023 at 06:25:15 UTC, Imperatorn wrote:On Friday, 13 October 2023 at 18:24:08 UTC, Adam D Ruppe wrote:yes. this would break existing code.On Friday, 13 October 2023 at 17:31:29 UTC, bachmeier wrote:We just want to be able to do string s = "Hello {name}, you are {age} years old and have {money - 42} dollars in the bank"; Is it too much to ask? 😭I don't know, but I also don't know why I would want to, because DIP 1027 was not accepted.dip 1027 was utter trash, but there's future good dips that would easily solve these things. pity D's leadership is so clueless and obstinate.
Oct 14 2023
On Saturday, 14 October 2023 at 06:25:15 UTC, Imperatorn wrote:On Friday, 13 October 2023 at 18:24:08 UTC, Adam D Ruppe wrote:Why does not this work for you? ```d string s = text("Hello ",name,", you are ",age," years old and have ",money - 42," dollars in the bank"); ```On Friday, 13 October 2023 at 17:31:29 UTC, bachmeier wrote:We just want to be able to do string s = "Hello {name}, you are {age} years old and have {money - 42} dollars in the bank"; Is it too much to ask? 😭I don't know, but I also don't know why I would want to, because DIP 1027 was not accepted.dip 1027 was utter trash, but there's future good dips that would easily solve these things. pity D's leadership is so clueless and obstinate.
Oct 14 2023
On Saturday, 14 October 2023 at 14:47:26 UTC, Andrey Zherikov wrote:On Saturday, 14 October 2023 at 06:25:15 UTC, Imperatorn wrote:Too many unnecessary quotes and commas, tedious to write and read. And for debug purpose I also want to print the variable names ... string interpolation is nothing fancy, but just syntax sugar to make the life easier. People have been asking it for years, but still not available. So, why not just do it?On Friday, 13 October 2023 at 18:24:08 UTC, Adam D Ruppe wrote:Why does not this work for you? ```d string s = text("Hello ",name,", you are ",age," years old and have ",money - 42," dollars in the bank"); ```On Friday, 13 October 2023 at 17:31:29 UTC, bachmeier wrote:We just want to be able to do string s = "Hello {name}, you are {age} years old and have {money - 42} dollars in the bank"; Is it too much to ask? 😭I don't know, but I also don't know why I would want to, because DIP 1027 was not accepted.dip 1027 was utter trash, but there's future good dips that would easily solve these things. pity D's leadership is so clueless and obstinate.
Oct 14 2023
On Saturday, 14 October 2023 at 14:47:26 UTC, Andrey Zherikov wrote:On Saturday, 14 October 2023 at 06:25:15 UTC, Imperatorn wrote:On Friday, 13 October 2023 at 18:24:08 UTC, Adam D Ruppe wrote:Why does not this work for you? ```d string s = text("Hello ",name,", you are ",age," years old and have ",money - 42," dollars in the bank"); ```On Friday, 13 October 2023 at 17:31:29 UTC, bachmeier wrote:We just want to be able to do string s = "Hello {name}, you are {age} years old and have {money - 42} dollars in the bank"; Is it too much to ask? 😭I don't know, but I also don't know why I would want to, because DIP 1027 was not accepted.dip 1027 was utter trash, but there's future good dips that would easily solve these things. pity D's leadership is so clueless and obstinate.
Oct 14 2023
On Saturday, 14 October 2023 at 14:47:26 UTC, Andrey Zherikov wrote:Why does not this work for you? ```d string s = text("Hello ",name,", you are ",age," years old and have ",money - 42," dollars in the bank"); ```We had a discussion on this a few years ago where someone said the same thing, but they had a missing space, and it wasn't immediately obvious. I'll sometimes create strings that are fed to the shell. Keeping the quoting straight is not the highlight of your day. That was probably the reason I rolled my own solution. `text` works for some things, but I find other approaches easier on the brain cells. I don't mind typing a few extra characters. I want to write it once and know I never have to think about it again.
Oct 14 2023
On Saturday, 14 October 2023 at 14:47:26 UTC, Andrey Zherikov wrote:Why does not this work for you? ```d string s = text("Hello ",name,", you are ",age," years old and have ",money - 42," dollars in the bank"); ```Check the first post.
Oct 14 2023
On Saturday, 14 October 2023 at 20:05:42 UTC, Andrea Fontana wrote:On Saturday, 14 October 2023 at 14:47:26 UTC, Andrey Zherikov wrote:I would actually be fine with smith like interp!"Hello {name}, your name is {name} and you have {money -42} dollars in the bank" until he have a character to use for itWhy does not this work for you? ```d string s = text("Hello ",name,", you are ",age," years old and have ",money - 42," dollars in the bank"); ```Check the first post.
Oct 15 2023
On Sunday, 15 October 2023 at 07:10:06 UTC, Imperatorn wrote:On Saturday, 14 October 2023 at 20:05:42 UTC, Andrea Fontana wrote:Typo but you get the point 😅On Saturday, 14 October 2023 at 14:47:26 UTC, Andrey Zherikov wrote:I would actually be fine with smith like interp!"Hello {name}, your name is {name} and you have {money -42} dollars in the bank" until he have a character to use for itWhy does not this work for you? ```d string s = text("Hello ",name,", you are ",age," years old and have ",money - 42," dollars in the bank"); ```Check the first post.
Oct 15 2023
On Sunday, 15 October 2023 at 07:10:39 UTC, Imperatorn wrote:On Sunday, 15 October 2023 at 07:10:06 UTC, Imperatorn wrote:Yes these versions are fine too i"hello ${world+1} $another_var" or: """hello ${word+1} $another_var""" or: $"hello ${world+1} $another_var" or: "hello %{world+1} %another_var"! or whatever enables string interpolation :)On Saturday, 14 October 2023 at 20:05:42 UTC, Andrea Fontana wrote:Typo but you get the point 😅On Saturday, 14 October 2023 at 14:47:26 UTC, Andrey Zherikov wrote:I would actually be fine with smith like interp!"Hello {name}, your name is {name} and you have {money -42} dollars in the bank" until he have a character to use for itWhy does not this work for you? ```d string s = text("Hello ",name,", you are ",age," years old and have ",money - 42," dollars in the bank"); ```Check the first post.
Oct 15 2023
On Sunday, 15 October 2023 at 08:18:04 UTC, Andrea Fontana wrote:On Sunday, 15 October 2023 at 07:10:39 UTC, Imperatorn wrote:Agreed!On Sunday, 15 October 2023 at 07:10:06 UTC, Imperatorn wrote:Yes these versions are fine too i"hello ${world+1} $another_var" or: """hello ${word+1} $another_var""" or: $"hello ${world+1} $another_var" or: "hello %{world+1} %another_var"! or whatever enables string interpolation :)On Saturday, 14 October 2023 at 20:05:42 UTC, Andrea Fontana wrote:Typo but you get the point 😅On Saturday, 14 October 2023 at 14:47:26 UTC, Andrey Zherikov wrote:I would actually be fine with smith like interp!"Hello {name}, your name is {name} and you have {money -42} dollars in the bank" until he have a character to use for it[...]Check the first post.
Oct 15 2023
On 10/13/2023 11:24 AM, Adam D Ruppe wrote:pity D's leadership is so clueless and obstinate.Criticize ideas, not people. Personal attacks are not welcome here.
Oct 17 2023
On Thursday, 12 October 2023 at 13:39:46 UTC, Andrea Fontana wrote:Real life example. Render a string like this: ``` \x1b[2K\r\x1b[1mProgress:\x1b[0m 50% \x1b[1m\tSpeed:\x1b[0m 15.5 KB/s ``` now (error prone and difficult to debug, try to code it!): ``` stderr.write(format("%s\r%sProgress:%s %5.1f%% %s\tSpeed:%s %6.1f %s%s", clear, white, clear, progress, white, clear, curSpeed, unit)); ``` (or with string concat, good luck!) vs: ``` stderr.write("${clear}\r{$white}Progress:${clear}${progress}% \t${white}Speed:${clear} ${curSpeed} ${unit}"); ```There are library solutions, e.g shameless self-plug: https://code.dlang.org/packages/jdiutil ``` writeln(mixin(_S!"with var name: {i; d; thePoint}")); ``` output: ``` with var name: i=100 d=1.23457 thePoint=app.Point(_x=3 _y=0.456 _label=default value _counter=0) ```
Oct 12 2023
On Thursday, 12 October 2023 at 17:56:29 UTC, mw wrote:On Thursday, 12 October 2023 at 13:39:46 UTC, Andrea Fontana wrote:The package is called: Just-Do-It Because things like this have been talked about so long ,and so many times (and even so many previous DIPs), but nothing materialized. So, I decided Just-Do-It!Real life example. Render a string like this: ``` \x1b[2K\r\x1b[1mProgress:\x1b[0m 50% \x1b[1m\tSpeed:\x1b[0m 15.5 KB/s ``` now (error prone and difficult to debug, try to code it!): ``` stderr.write(format("%s\r%sProgress:%s %5.1f%% %s\tSpeed:%s %6.1f %s%s", clear, white, clear, progress, white, clear, curSpeed, unit)); ``` (or with string concat, good luck!) vs: ``` stderr.write("${clear}\r{$white}Progress:${clear}${progress}% \t${white}Speed:${clear} ${curSpeed} ${unit}"); ```There are library solutions, e.g shameless self-plug: https://code.dlang.org/packages/jdiutil ``` writeln(mixin(_S!"with var name: {i; d; thePoint}")); ``` output: ``` with var name: i=100 d=1.23457 thePoint=app.Point(_x=3 _y=0.456 _label=default value _counter=0) ```
Oct 12 2023
On Thursday, 12 October 2023 at 13:39:46 UTC, Andrea Fontana wrote:Real life example. Render a string like this: ``` \x1b[2K\r\x1b[1mProgress:\x1b[0m 50% \x1b[1m\tSpeed:\x1b[0m 15.5 KB/s ``` now (error prone and difficult to debug, try to code it!): ``` stderr.write(format("%s\r%sProgress:%s %5.1f%% %s\tSpeed:%s %6.1f %s%s", clear, white, clear, progress, white, clear, curSpeed, unit)); ``` (or with string concat, good luck!) vs: ``` stderr.write("${clear}\r{$white}Progress:${clear}${progress}% \t${white}Speed:${clear} ${curSpeed} ${unit}"); ``` AndreaIf you are using `write*` then you can simply do this: ```d stderr.write(clear,"\r",white,"Progress:",clear," ",progress,"% ",white,"\tSpeed:",clear," ",curSpeed," ",unit); ``` If you want just to get a string - use `text`: ```d stderr.write(text(clear,"\r",white,"Progress:",clear," ",progress,"% ",white,"\tSpeed:",clear," ",curSpeed," ",unit)); ``` The result is the same so IMHO `text` is good alternative to string interpolation. You can also wrap styling into functions to make code more readable: ```d string white(A...)(A args) { return text("\x1b[1m", args, "\x1b[0m"); } stderr.write(clear,"\r",white("Progress: "),progress,"% \t",white("Speed: "),curSpeed," ",unit); ```
Oct 12 2023
On Thursday, 12 October 2023 at 13:39:46 UTC, Andrea Fontana wrote:Real life example. Render a string like this: ``` \x1b[2K\r\x1b[1mProgress:\x1b[0m 50% \x1b[1m\tSpeed:\x1b[0m 15.5 KB/s ``` now (error prone and difficult to debug, try to code it!):Where is the specific problem? ``` import std.stdio; int main (string [] args) { enum fmt = "\x1b[2K\r\x1b[1mProgress:\x1b[0m %s%% \x1b[1m\tSpeed:\x1b[0m > %s KB/s"; writeln (fmt); writefln!fmt (75, 11.11); return 0; } $ ./prgs Progress: %s%% Speed: > %s KB/s Progress: 75% Speed: > 11.11 KB/s ``` The words `Progress` and `Speed` appear highlighted in my console.
Oct 13 2023
On 10/12/2023 6:39 AM, Andrea Fontana wrote:``` stderr.write("${clear}\r{$white}Progress:${clear}${progress}% \t${white}Speed:${clear} ${curSpeed} ${unit}"); ```With DIP1027: ``` stderr.write("$clear\r$(white)Progress:$clear$progress% \t$(white)Speed:$clear $curSpeed $unit"); ``` If it's a simple identifier, the { } are not necessary. https://github.com/dlang/DIPs/blob/master/DIPs/rejected/DIP1027.md#description
Oct 17 2023
On 10/17/2023 10:24 AM, Walter Bright wrote:``` stderr.write("$clear\r$(white)Progress:$clear$progress% \t$(white)Speed:$clear $curSpeed $unit"); ```Oops, forgot the leading 'i': ``` stderr.write(i"$clear\r$(white)Progress:$clear$progress% \t$(white)Speed:$clear $curSpeed $unit"); ```
Oct 17 2023
On Tuesday, 17 October 2023 at 17:27:41 UTC, Walter Bright wrote:Oops, forgot the leading 'i': ``` stderr.write(i"$clear\r$(white)Progress:$clear$progress% \t$(white)Speed:$clear $curSpeed $unit"); ```Still won't work. Your dip1027 would write %s\r%sProgress:%s%s%\t%sSpeed:%s %s %s\e[09m\e01m5\[30m\0[09m5bytes/sec if you used it like that. This is one of the reasons why it was rejected. If we want to move forward, there's actually a good proposal out there: https://github.com/John-Colvin/YAIDIP
Oct 17 2023
On 10/17/2023 10:37 AM, Adam D Ruppe wrote:On Tuesday, 17 October 2023 at 17:27:41 UTC, Walter Bright wrote:That's a misunderstanding of how it works.Oops, forgot the leading 'i': ``` stderr.write(i"$clear\r$(white)Progress:$clear$progress% \t$(white)Speed:$clear $curSpeed $unit"); ```Still won't work. Your dip1027 would write %s\r%sProgress:%s%s%\t%sSpeed:%s %s %s\e[09m\e01m5\[30m\0[09m5bytes/sec if you used it like that.
Oct 17 2023
On Tuesday, 17 October 2023 at 19:03:48 UTC, Walter Bright wrote:That's a misunderstanding of how it works.No, that's exactly how it works. Read the document: writefln(i"I ate $apples and ${%d}bananas totalling $(apples + bananas) fruit."); gets rewritten as: writefln("I ate %s and %d totalling %s fruit.", apples, bananas, apples + bananas); And read the post above, which uses *write*, not write*f*. Think about the implications of that for a second.
Oct 17 2023
On 10/17/2023 12:20 PM, Adam D Ruppe wrote:And read the post above, which uses *write*, not write*f*. Think about the implications of that for a second.Yes, it means I forgot to use writef instead of write.
Oct 17 2023
On Tuesday, 17 October 2023 at 20:05:59 UTC, Walter Bright wrote:On 10/17/2023 12:20 PM, Adam D Ruppe wrote:Your version left off the format specifiers, but I don't think that's all that significant.And read the post above, which uses *write*, not write*f*. Think about the implications of that for a second.Yes, it means I forgot to use writef instead of write.
Oct 17 2023
On 10/17/2023 1:23 PM, jmh530 wrote:The %s format specifiers are inserted by default.Yes, it means I forgot to use writef instead of write.Your version left off the format specifiers, but I don't think that's all that significant.
Oct 17 2023
On Tuesday, 17 October 2023 at 20:05:59 UTC, Walter Bright wrote:Yes, it means I forgot to use writef instead of write.And the compiler wouldn't have told you about this. This is one of the (several) reasons why the dip was rejected. and Javascript both have much better facilities.
Oct 17 2023
On 10/17/2023 1:44 PM, Adam D Ruppe wrote:On Tuesday, 17 October 2023 at 20:05:59 UTC, Walter Bright wrote:Neither would YAIDIP. write() takes a variadic argument list. YAIDIP also requires the correct version of user-defined InterpolationHeader to be the one in scope. It's not immediately clear what would happen if the wrong one was in scope.Yes, it means I forgot to use writef instead of write.And the compiler wouldn't have told you about this.
Oct 17 2023
On Wednesday, 18 October 2023 at 00:27:16 UTC, Walter Bright wrote:Neither would YAIDIP. write() takes a variadic argument list.Which is irrelevant because it *works correctly* when passed to write(), so there's no need for the compiler to say anything.YAIDIP also requires the correct version of user-defined InterpolationHeader to be the one in scope.The text of the yaidip doesn't specify this, but this is utterly trivial to solve; the dip 1036 specified a fully qualified name for it and this one could too.
Oct 17 2023
On Wednesday, 18 October 2023 at 00:45:40 UTC, Adam D Ruppe wrote:The text of the yaidip doesn't specify thisActually, looking again, it states: "Every i-string lowering introduces a header rvalue object that so far we conventionally denoted as __header (the exact name is uniquely compiler-generated and hence inaccessible)." so this may not matter anyway, nevertheless, I just did the 30 second find+replace of the abbreviated name with the fully qualified name to concretely specify this. Refresh the page.
Oct 17 2023
On 10/17/2023 6:07 PM, Adam D Ruppe wrote:On Wednesday, 18 October 2023 at 00:45:40 UTC, Adam D Ruppe wrote:How does the user specify the fully-qualified name of a compiler generated object?The text of the yaidip doesn't specify thisActually, looking again, it states: "Every i-string lowering introduces a header rvalue object that so far we conventionally denoted as __header (the exact name is uniquely compiler-generated and hence inaccessible)." so this may not matter anyway, nevertheless, I just did the 30 second find+replace of the abbreviated name with the fully qualified name to concretely specify this. Refresh the page.
Oct 17 2023
On 10/17/2023 5:45 PM, Adam D Ruppe wrote:On Wednesday, 18 October 2023 at 00:27:16 UTC, Walter Bright wrote:I don't see how, from my reading of the proposal. It doesn't matter that much if write() does not give a compile time error, as this is normal and accepted for variadic functions. But as you've characterized it as a fatal error, the YAIDIP spec should be improved to address it.Neither would YAIDIP. write() takes a variadic argument list.Which is irrelevant because it *works correctly* when passed to write(), so there's no need for the compiler to say anything.If it's trivial, then please fix the proposal. BTW, it's normal to uncover errors like this in a proposal for a new feature.YAIDIP also requires the correct version of user-defined InterpolationHeader to be the one in scope.The text of the yaidip doesn't specify this, but this is utterly trivial to solve; the dip 1036 specified a fully qualified name for it and this one could too.
Oct 17 2023
On Wednesday, 18 October 2023 at 02:19:21 UTC, Walter Bright wrote:I don't see how, from my reading of the proposal.The first example under the Description shows this exact situation and then goes on to explain how and why it works as expected.But as you've characterized it as a fatal error, the YAIDIP spec should be improved to address it.It is a fatal error for YOUR (rejected) dip 1027, as it silently leads to wrong results in common cases. This was all explained in detail in the review process four years ago. Things work correctly with this proposal, you either get the expected results or a compiler error, as a natural consequence of the existing type system. Nothing needs to be spelled out about this as there are not any special cases.If it's trivial, then please fix the proposal.Already did, over an hour ago. It took about 30 seconds to specify. This isn't a big deal. (And btw, even if it didn't specify, the behavior is well-defined in the D Programming Language, and such things are already similar in other places, including other existing compiler hooks, see _d_cmain <http://dpldocs.info/this-week-in-d/Blog.Posted_2022_07_18.html>. But now the text does specify the fully qualified name anyway, so this is all moot.
Oct 17 2023
On 10/17/2023 7:39 PM, Adam D Ruppe wrote:On Wednesday, 18 October 2023 at 02:19:21 UTC, Walter Bright wrote:The line in question: ``` writeln(__header, "I ate ", apples, " apples and ", bananas, " bananas totalling ", apples + bananas, " fruit.") ``` What does writeln() do with __header?I don't see how, from my reading of the proposal.The first example under the Description shows this exact situation and then goes on to explain how and why it works as expected.Things work correctly with this proposal, you either get the expected results or a compiler error, as a natural consequence of the existing type system. Nothing needs to be spelled out about this as there are not any special cases.Does that mean writeln() gets rewritten to handle __header? If so, ok, but the YAIDIP doesn't say that. Today, the only difference between writef() and write() is the former takes the first argument as the format string. Is this a fatal error? I suppose you could consider it as one, but that's an issue typical with variadic functions.Already did, over an hour ago.Ok, I saw it after I posted that.It took about 30 seconds to specify. This isn't a big deal. (And btw, even if it didn't specify, the behavior is well-defined in the D Programming Language, and such things are already similar in other places, including other existing compiler hooks, see _d_cmain <http://dpldocs.info/this-week-in-d/Blog.Posted_2022_07_18.html>. But now the text does specify the fully qualified name anyway, so this is all moot.I think we're misunderstanding each other. What I am asking about is how does the user specify his own custom implementation of InterpolatedExpression?
Oct 17 2023
On Wednesday, 18 October 2023 at 03:57:52 UTC, Walter Bright wrote:The line in question: ``` writeln(__header, "I ate ", apples, " apples and ", bananas, " bananas totalling ", apples + bananas, " fruit.") ``` What does writeln() do with __header?__header is implicitly converted to null string by writeln (the struct will have a toString method that returns null), so from the point of view of existing text methods such as writeln, text, everything is fine.Does that mean writeln() gets rewritten to handle __header? If so, ok, but the YAIDIP doesn't say that. Today, the only difference between writef() and write() is the former takes the first argument as the format string. Is this a fatal error? I suppose you could consider it as one, but that's an issue typical with variadic functions.It's a pain to parse it (DIP 1027) when you'd like to define your own function accepting interpolated strings, compared to suggested DIP.I think the assumption is that __header type is passed as template argument, then there are no issues with voldemort types. If you really like to specify type not through template argument, I guess DIP could be enhanced saying that __header could implicitly convert to a predefined struct, i.e. RuntimeStoredInterpolationInfo. Best regards, Alexandru.Already did, over an hour ago.Ok, I saw it after I posted that.It took about 30 seconds to specify. This isn't a big deal.I think we're misunderstanding each other. What I am asking about is how does the user specify his own custom implementation of InterpolatedExpression?
Oct 18 2023
On 10/18/2023 12:53 AM, Alexandru Ermicioi wrote:__header is implicitly converted to null string by writeln (the struct will have a toString method that returns null), so from the point of view of existing text methods such as writeln, text, everything is fine.Ok. So does the user have to define his own InterpolatedExpression to get something different to happen?
Oct 18 2023
On Wednesday, 18 October 2023 at 03:57:52 UTC, Walter Bright wrote:What does writeln() do with __header?"The __header value, to be discussed later, is generated by the compiler and contains compile-time information about the interpolated string." <a few moments later> "The header object has a trivial toString method that expands to the null string. This method makes it possible to pass interpolated strings directly to functions such as writeln and text because these functions detect and use toString to convert unknown data types to strings." It just uses the existing rules for a struct. No special case here. It doesn't spell this out, but you can think about what happens to normal D functions if you pass some `struct` to a function expecting a `string` - an ordinary type mismatch error. This is what gives library authors such power with this proposal: they can overload a function to provided specialized behavior. Which brings me to:I think we're misunderstanding each other. What I am asking about is how does the user specify his own custom implementation of InterpolatedExpression?There's no need. You just pass it to a function. Library authors overload functions on the type of what was passed, including an interpolated type if desired, same as any other overload. End users call a particular function uses the given arguments to create their desired result; a generic function forwarder still works, preserving the full interpolated argument, since it works like any other set of function arguments. This gives *enormous* capability to both sides - mostly by using already existing features in the D language.
Oct 18 2023
On 10/18/2023 1:27 PM, Adam D Ruppe wrote:On Wednesday, 18 October 2023 at 03:57:52 UTC, Walter Bright wrote:Ok. The lowering to arguments to InterpolatedExpression seem to all be string versions of the argument identifiers, rather than what the types are. "the header gives the callee complete access to the strings corresponding to the expressions passed in." I don't know what that is useful for. Note that if write() is a template, it already has access to all the arguments and their types.What does writeln() do with __header?"The __header value, to be discussed later, is generated by the compiler and contains compile-time information about the interpolated string." <a few moments later> "The header object has a trivial toString method that expands to the null string. This method makes it possible to pass interpolated strings directly to functions such as writeln and text because these functions detect and use toString to convert unknown data types to strings." It just uses the existing rules for a struct. No special case here. It doesn't spell this out, but you can think about what happens to normal D functions if you pass some `struct` to a function expecting a `string` - an ordinary type mismatch error. This is what gives library authors such power with this proposal: they can overload a function to provided specialized behavior.Library authors overload functions on the type of what was passed, including an interpolated type if desired, same as any other overload. End users call a particular function uses the given arguments to create their desired result; a generic function forwarder still works, preserving the full interpolated argument, since it works like any other set of function arguments. This gives *enormous* capability to both sides - mostly by using already existing features in the D language.I'd like to see an example of code of how this customization might work, because I don't see it. P.S. there are several errors in the document, such as '$' appearing in the lowered code. What "normalization" means is unclear.
Oct 18 2023
On Thursday, 19 October 2023 at 00:57:35 UTC, Walter Bright wrote:The lowering to arguments to InterpolatedExpression seem to all be string versions of the argument identifiers, rather than what the types are.The types are attached to the parameters themselves, so it is purely redundant to list them again. The interpolated header's job is to preserve the original string, allowing for compile time manipulation of it. The arguments are processed the same as any other `T...` tuple in D."the header gives the callee complete access to the strings corresponding to the expressions passed in." I don't know what that is useful for. Note that if write() is a template, it already has access to all the arguments and their types.The strings are not the types. The compiler has this information, the user wrote it, even if you don't see the value, why discard it? But here's one example: this year's DConf had a talk on gnu gettext. In current D code, they use a template argument string to make a user-defined literal which is collected into the translation files. This is pretty cool. But it loses some information, comments are added by hand: tr!("One license.", "%d licenses.", Context(“driver's"))(n); With the interpolation header, it could quite plausibly be: tr(i"One license.", i"$(driversLicenseCount) licenses."); (i renamed the variable there because it is now meaningful so you can). The full string written in the source - i"$(driversLicenseCount) licenses." - is available for inspection. The tr function can even extract that variable name and automatically add it as a comment to the translator, giving them the additional context without needing to write it again in the code. It also potentially opens up library implementations of something like assert with checkaction=context, showing the original code that led to the result. Please note that it is just a string in another scope, it is not useful for `mixin` or anything like that. You still inspect the *value* using the argument. But the *string* can be used as a *string* for these other tasks.I'd like to see an example of code of how this customization might work, because I don't see it.Element makeHtmlFromTemplate(T...)(T t) if(T.length && is(T[0] == core.interpolation.InterpolationHeader!Parts, Parts...)) { string html; foreach(idx, str; Parts) { if(idx % 2 == 0) html ~= str; // i know this is html string literal thanks to noramlization else // note i also know what code this came from in case i need it for error messages, debug info, etc, it is in `str` html ~= htmlEntitiesEncode(to!string(t[idx / 2])); } return Element.make(Html(html)); } auto element = makeHtmlFromTemplate(i` <html> <p class="foo" title="$(title)"> $(content) </p> </html> `); Note the VERY important fact that the makeHtmlFromTemplate *knows for a fact* what is html and what is data coming from the outside, so it can be sure about what to encode and what not to. Also worth noting it has the option of validating the HTML at compile time, using CTFE, because it can reconstruct the string from the InterpolationHeader too - this is a runtime error in most languages, but in D it doesn't have to be. Javascript can do this kind of thing, with runtime error throwing. The JSX extensions to the language exist to add compile time validation. D ought to be able to do the same thing *without* a custom add-on compiler. We have CTFE.P.S. there are several errors in the document, such as '$' appearing in the lowered code. What "normalization" means is unclear.typos are irrelevant but whatever i'll fix them. "Normalization" means what it says under the "normalization" header, which ensures you can distinctively tell the difference between format string and arguments.
Oct 18 2023
On 10/18/2023 7:47 PM, Adam D Ruppe wrote:Thanks for the example. I thought I'd show the equivalent with DIP1027. It's a bit crude, and I didn't bother with the details of html generation, but this shows the method and can be compiled and run: ``` import std.conv; string makeHtmlFromTemplate(Parts...)(const char[] fmt, Parts parts) { string html; size_t i; void advance() { while (i < fmt.length) { if (fmt[i] == '%' && i + 1 < fmt.length && fmt[i + 1] == 's') { i += 2; return; } html ~= fmt[i]; ++i; } } advance(); foreach (part; parts) { html ~= to!string(part); // or htmlEntityEncode advance(); } return html; } void main() { import std.stdio; string abc = "def"; string html = makeHtmlFromTemplate("format %s %s sss", abc, 73); // tuple generated by DIP1027 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // from i"format $abc $(73) sss" writeln(html); } ``` which prints: format def 73 sss This code can be adapted to do whatever output schema one wants. Compare the tuple generated by DIP1027: ``` tuple("format %s %s sss", abc, 73) ``` and with YAIDIP: ``` tuple(.object.imported!"core.interpolation".InterpolationHeader!("", "format ", "", abc, "", 73, "", " sss", ""), "", "format ", "", abc, "", 73, "", " sss", "") ```I'd like to see an example of code of how this customization might work, because I don't see it.Element makeHtmlFromTemplate(T...)(T t) if(T.length && is(T[0] == core.interpolation.InterpolationHeader!Parts, Parts...)) { string html; foreach(idx, str; Parts) { if(idx % 2 == 0) html ~= str; // i know this is html string literal thanks to noramlization else // note i also know what code this came from in case i need it for error messages, debug info, etc, it is in `str` html ~= htmlEntitiesEncode(to!string(t[idx / 2])); } return Element.make(Html(html)); } auto element = makeHtmlFromTemplate(i` <html> <p class="foo" title="$(title)"> $(content) </p> </html> `);
Oct 20 2023
On Friday, 20 October 2023 at 07:14:45 UTC, Walter Bright wrote:On 10/18/2023 7:47 PM, Adam D Ruppe wrote:Whatever happens, can we please either merge the new dip or your dip? Please? Whatever dip is the simplest and performs the best should win. Just so we get somewhere. The community is begging you all to settle for something. Maybe a "winner" could be chosen emperically instead? Write some examples and run. Measure the performance. Fastest that is also currect wins. Easy 😍[...]Thanks for the example. I thought I'd show the equivalent with DIP1027. It's a bit crude, and I didn't bother with the details of html generation, but this shows the method and can be compiled and run: ``` import std.conv; string makeHtmlFromTemplate(Parts...)(const char[] fmt, Parts parts) { string html; size_t i; void advance() { while (i < fmt.length) { if (fmt[i] == '%' && i + 1 < fmt.length && fmt[i + 1] == 's') { i += 2; return; } html ~= fmt[i]; ++i; } } advance(); foreach (part; parts) { html ~= to!string(part); // or htmlEntityEncode advance(); } return html; } void main() { import std.stdio; string abc = "def"; string html = makeHtmlFromTemplate("format %s %s sss", abc, 73); // tuple generated by DIP1027 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // from i"format $abc $(73) sss" writeln(html); } ``` which prints: format def 73 sss This code can be adapted to do whatever output schema one wants. Compare the tuple generated by DIP1027: ``` tuple("format %s %s sss", abc, 73) ``` and with YAIDIP: ``` tuple(.object.imported!"core.interpolation".InterpolationHeader!("", "format ", "", abc, "", 73, "", " sss", ""), "", "format ", "", abc, "", 73, "", " sss", "") ```
Oct 20 2023
On Friday, 20 October 2023 at 07:14:45 UTC, Walter Bright wrote:``` tuple("format %s %s sss", abc, 73) ```This requires cumbersome workarounds for the format string to be accessible at compile time: alias tmp = i"format %s %s sss"; string html = makeHtmlFromTemplate!(tmp[0])(tmp[1..$]); The simple tuple approach could work in Zig - they have "comptime" for partial evaluation (D's old 'static' function parameters plan put into practice).
Oct 20 2023
On Friday, 20 October 2023 at 08:26:35 UTC, Max Samukha wrote:On Friday, 20 October 2023 at 07:14:45 UTC, Walter Bright wrote:I didn't know about that old "'static' function parameters", what was that?``` tuple("format %s %s sss", abc, 73) ```This requires cumbersome workarounds for the format string to be accessible at compile time: alias tmp = i"format %s %s sss"; string html = makeHtmlFromTemplate!(tmp[0])(tmp[1..$]); The simple tuple approach could work in Zig - they have "comptime" for partial evaluation (D's old 'static' function parameters plan put into practice).
Oct 20 2023
On Friday, 20 October 2023 at 09:43:47 UTC, Imperatorn wrote:I didn't know about that old "'static' function parameters", what was that?`void foo(static T t);`
Oct 20 2023
On Friday, 20 October 2023 at 07:14:45 UTC, Walter Bright wrote:This code can be adapted to do whatever output schema one wants. Compare the tuple generated by DIP1027: ``` tuple("format %s %s sss", abc, 73) ``` and with YAIDIP: ``` tuple(.object.imported!"core.interpolation".InterpolationHeader!("", "format ", "", abc, "", 73, "", " sss", ""), "", "format ", "", abc, "", 73, "", " sss", "") ```If this is supposed to be a favorable comparison of 1027, this has failed. 1027 requires runtime processing of a compile-time format string. It requires that you implement escapes for the %s spec and for literal %, or just know that your domain doesn't have a valid use for %s normally (though this always can be proven to be a mistake by users). It is not friendly to multiple interpolation strings sent to the same function (how does the function know this is a new header?) YAIDIP or 1036, there is no discarding of the processing the *compiler already did* to parse the format string. Think about that -- with 1027 the compiler parsed the interpolation tuple, and built a puzzle string for you to have to figure out what it did during runtime. Who cares what the generated tuple looks like? Nobody will see it. Do you care what other lowerings in the compiler look like? Because a lot of times they are god-awful monstrosities that nobody would write themselves. Is that something to object to? All the proposed solutions, including 1027, can be worked with for most cases. It's just that the code to adapt 1027 to calls except for printf and writef is awful. It doesn't handle other situations at all. And 1027 still has the problem of matching functions it shouldn't match. Do you recall Adam's example of exception construction? ```d throw new Exception(i"Invalid integer value in $file: $val"); ``` -Steve
Oct 20 2023
On Friday, 20 October 2023 at 13:45:40 UTC, Steven Schveighoffer wrote:On Friday, 20 October 2023 at 07:14:45 UTC, Walter Bright wrote:I'm just happy that I now can do this ![String interpolation](https://i.ibb.co/4WVYSnr/interp.gif) Next is just to integrate into the rest of the tools.This code can be adapted to do whatever output schema one wants. Compare the tuple generated by DIP1027:
Oct 20 2023
On Friday, 20 October 2023 at 14:13:44 UTC, Imperatorn wrote:On Friday, 20 October 2023 at 13:45:40 UTC, Steven Schveighoffer wrote:Just look at this. You know you want it 😅On Friday, 20 October 2023 at 07:14:45 UTC, Walter Bright wrote:I'm just happy that I now can do this ![String interpolation](https://i.ibb.co/4WVYSnr/interp.gif) Next is just to integrate into the rest of the tools.This code can be adapted to do whatever output schema one wants. Compare the tuple generated by DIP1027:
Oct 20 2023
On Friday, 20 October 2023 at 15:47:17 UTC, Imperatorn wrote:On Friday, 20 October 2023 at 14:13:44 UTC, Imperatorn wrote:LGTM merge... (if I could :p)On Friday, 20 October 2023 at 13:45:40 UTC, Steven Schveighoffer wrote:Just look at this. You know you want it 😅On Friday, 20 October 2023 at 07:14:45 UTC, Walter Bright wrote:I'm just happy that I now can do this ![String interpolation](https://i.ibb.co/4WVYSnr/interp.gif) Next is just to integrate into the rest of the tools.This code can be adapted to do whatever output schema one wants. Compare the tuple generated by DIP1027:
Oct 20 2023
On Friday, 20 October 2023 at 16:15:52 UTC, Daniel N wrote:On Friday, 20 October 2023 at 15:47:17 UTC, Imperatorn wrote:On Friday, 20 October 2023 at 14:13:44 UTC, Imperatorn wrote:On Friday, 20 October 2023 at 13:45:40 UTC, Steven Schveighoffer wrote:On Friday, 20 October 2023 at 07:14:45 UTC, Walter Bright wrote:LGTM merge... (if I could :p)Hehe, I posted some instructions here if you want to try it out: https://forum.dlang.org/post/rkevblyfgvmvmsuhtqmr forum.dlang.org
Oct 20 2023
On Friday, 20 October 2023 at 13:45:40 UTC, Steven Schveighoffer wrote:On Friday, 20 October 2023 at 07:14:45 UTC, Walter Bright wrote:thank you. i agree, YAIDIP is the best solution so far, but i think we should take a step back and think about the real porblem: why can't we do it with existing language features, and what would be required to simply make ```foo(i!"cool ${var} rox");``` work instead. because adding that feature might benefit a lot more use cases.[...]If this is supposed to be a favorable comparison of 1027, this has failed. 1027 requires runtime processing of a compile-time format string. It requires that you implement escapes for the %s spec and for literal %, or just know that your domain doesn't have a valid use for %s normally (though this always can be proven to be a mistake by users). It is not friendly to multiple interpolation strings sent to the same function (how does the function know this is a new header?) YAIDIP or 1036, there is no discarding of the processing the *compiler already did* to parse the format string. Think about that -- with 1027 the compiler parsed the interpolation tuple, and built a puzzle string for you to have to figure out what it did during runtime. Who cares what the generated tuple looks like? Nobody will see it. Do you care what other lowerings in the compiler look like? Because a lot of times they are god-awful monstrosities that nobody would write themselves. Is that something to object to? All the proposed solutions, including 1027, can be worked with for most cases. It's just that the code to adapt 1027 to calls except for printf and writef is awful. It doesn't handle other situations at all. And 1027 still has the problem of matching functions it shouldn't match. Do you recall Adam's example of exception construction? ```d throw new Exception(i"Invalid integer value in $file: $val"); ``` -Steve
Oct 20 2023
On Friday, 20 October 2023 at 15:29:29 UTC, Commander Zot wrote:why can't we do it with existing language features, and what would be required to simply make ```foo(i!"cool ${var} rox");``` work instead. because adding that feature might benefit a lot more use cases.Because templates are lexically scoped, the body of the `i` template would not be able to access `var` when expanding the string `"cool ${var} rox"`. The only way in D for a template to access the scope where it's *used* instead of the scope where it's *defined* is to use a `mixin` (either string or template). So the best we can do with current language features is `foo(mixin(i!"cool ${var} rox"))`. (And indeed, there are libraries on code.dlang.org that do this.) So, I guess the minimal language feature that would allow your example to work would be the ability to define a template whose result is implicitly mixed-in to the instantiating scope, without having to use the `mixin` keyword. However, I doubt such a feature would be accepted. The whole point of requiring the `mixin` keyword is to signal to anyone reading the code that this is a place where D's normal scoping rules might be violated. Allowing that to happen implicitly would defeat the purpose of having a `mixin` keyword in the first place.
Oct 20 2023
On Friday, 20 October 2023 at 13:45:40 UTC, Steven Schveighoffer wrote:All the proposed solutions, including 1027, can be worked with for most cases. It's just that the code to adapt 1027 to calls except for printf and writef is awful. It doesn't handle other situations at all.I misspoke, 1027 doesn't actually handle `printf` very well, you still have to include the format specifiers for anything other than a `char *`. Only `writef` makes sense. Whereas, with DIP1036, I [already wrote](https://forum.dlang.org/post/rv6f0l$ke7$1 digitalmars.com) an overload that works with `printf` without needing any specifiers, and is betterC compatible, it should lower to one call to `core.stdc.stdio.printf`. ```d import core.stdc.stdio; import std.traits; struct interp(string s) { static string toString() { return s; } } alias printf = core.stdc.stdio.printf; auto printf(Args...)(Args args) if (isInstanceOf!(interp, Args[0])) { static immutable formatStr = () { string result; foreach(T; Args) static if(isInstanceOf!(interp, T)) result ~= T.toString(); else static if(is(T == int)) result ~= "%d"; else static if(is(T : const(char)[])) result ~= "%.*s"; else static if(is(T == float) || is(T == double)) result ~= "%f"; // .. and so on return result ~ "\0"; }(); mixin(() { string result = "return core.stdc.stdio.printf(formatStr.ptr"; foreach(i, T; Args) static if(!isInstanceOf!(interp, T)){ static if(is(T : const(char)[])) result ~= ", cast(int)args[" ~ i.stringof ~ "].length, args[" ~ i.stringof ~ "].ptr"; else result ~= ", args[" ~ i.stringof ~ "]"; } return result ~ ");"; }()); } extern(C) void main() { string name = "Walter"; int age = 42; // equivalent of printf(i"Hello, ${name}, you are ${age} years old.\n"); printf(interp!"Hello, "(), name, interp!", you are "(), age, interp!" years old.\n"()); printf("And normal printf works too, %s\n", name.ptr); } ``` -Steve
Oct 20 2023
On Tuesday, 17 October 2023 at 20:05:59 UTC, Walter Bright wrote:On 10/17/2023 12:20 PM, Adam D Ruppe wrote:The DIP linked by Adam is very appealing to me. All the modern programming languages I frequently use have some form of string interpolation, and when I write code in D, I miss it. I genuinely don't understand the opposition to such a highly desired feature that can only enhance code readability. I am less fond of the proposal related to printf/writef/writelnf/format/sformat, etc. It appears to add complexity to the code, introduces unnecessary noise, and is prone to errors. AndreaAnd read the post above, which uses *write*, not write*f*. Think about the implications of that for a second.Yes, it means I forgot to use writef instead of write.
Oct 18 2023
On Wednesday, 18 October 2023 at 22:43:56 UTC, Andrea Fontana wrote:I genuinely don't understand the opposition to such a highly desired feature that can only enhance code readability.Because the parts of the D community that are both vocal and motivated enough to discuss language improvements are a mix of opposing egos striving for their own visions of perfection, and any slight compromise is deemed unacceptable, unworkable, and nothing short of heresy in the eyes of the all mighty Perfect Solution. I mean this in a relatively sincere way as everyone wants what they think is best for the language, but failure to come to a common ground results in things like several years of on-and-off bike shedding around features other languages (that don't have the same challenges and complications as D for what its worth) could have pushed through several times over since then. features and syntax sugar they add, as it's often well designed, well integrated, has tooling support straight away, and generally just helps make code feel cleaner... (well not all the time lol). Meanwhile we still can't figure out a way to get string interpolation into the language that isn't shot dead in its entirety on arrival :D However if DIP1030 (Named arguments) - which I'm slightly surprise wasn't bikeshedded to rejection - managed to get through, then I'm optimistic in another 5 years we'll have settled on something for interpolation, whether it be outright rejection of the entire idea, or an actual implementable solution.
Oct 18 2023
On 10/18/2023 3:43 PM, Andrea Fontana wrote:I am less fond of the proposal related to printf/writef/writelnf/format/sformat, etc. It appears to add complexity to the codeExample of the complexity? It's probably the simplest string interpolation I could find.introduces unnecessary noiseExample please.is prone to errorsIt's not prone to errors any more than writef() is, because writef() checks the format against the type of the corresponding argument. As for printf(), we've added format string checking to printf() calls which have virtually eliminated such errors.
Oct 18 2023
On Thursday, 19 October 2023 at 01:05:59 UTC, Walter Bright wrote:On 10/18/2023 3:43 PM, Andrea Fontana wrote:For example: ``` string t = format(i"....")); ^^^^^^ ```I am less fond of the proposal related to printf/writef/writelnf/format/sformat, etc. It appears to add complexity to the codeExample of the complexity? It's probably the simplest string interpolation I could find.introduces unnecessary noiseExample please.Well, you know, even you posted a wrong example earlier in the thread. I'm also somewhat concerned about potential error messages that might confuse users due to the non-obvious abstraction: f.e. what happens if someone writes ```myfunction(i"hello $name!");``` Andreais prone to errors
Oct 19 2023
On 10/19/2023 12:29 AM, Andrea Fontana wrote:The error won't result in anything other than oops there's a format string in the output. If that's the only prone-ness to errors, it's doing very well.Well, you know, even you posted a wrong example earlier in the thread.is prone to errorsI'm also somewhat concerned about potential error messages that might confuse users due to the non-obvious abstraction: f.e. what happens if someone writes ```myfunction(i"hello $name!");```Do you mean someone accidentally prefixing with 'i'? How would that be any different from the other proposal?
Oct 19 2023
On Thursday, 19 October 2023 at 07:51:38 UTC, Walter Bright wrote:On 10/19/2023 12:29 AM, Andrea Fontana wrote:Not by mistake, but intentionally because I want to pass a formatted string to my function. And if I'm not mistaken, that string will be expanded into a tuple that could mess up the call to my function, returning an error that might confuse the user. In the worst case, it could call my function with extra parameters I didn't even expect, causing some unexpected side-effects. ``` // This function delete all the file passed (just a joke) void deleteFiles(string[]... files) { ... } // Example deleteFiles("/tmp/test.txt", "/tmp/old.txt"); deleteFiles(i"/tmp/$dirname/$file"); <-- ooops this will be expanded? ```The error won't result in anything other than oops there's a format string in the output. If that's the only prone-ness to errors, it's doing very well.Well, you know, even you posted a wrong example earlier in the thread.is prone to errorsI'm also somewhat concerned about potential error messages that might confuse users due to the non-obvious abstraction: f.e. what happens if someone writes ```myfunction(i"hello $name!");```Do you mean someone accidentally prefixing with 'i'? How would that be any different from the other proposal?
Oct 19 2023
As long as the literal cannot expand out into regular strings and only structs, this shouldn't be possible for it to occur silently. From there its just a matter of having good error message writing where it sees what you tried to do and tell you why its wrong. This can happen incrementally.
Oct 19 2023
On Thursday, 19 October 2023 at 10:53:08 UTC, Richard (Rikki) Andrew Cattermole wrote:As long as the literal cannot expand out into regular strings and only structs, this shouldn't be possible for it to occur silently. From there its just a matter of having good error message writing where it sees what you tried to do and tell you why its wrong. This can happen incrementally.But walter's proposal expands it to a tuple if I understand it correctly: https://github.com/dlang/DIPs/blob/148001a963f5d6e090bb6beef5caf9854372d0bc/DIPs/DIP1027.md
Oct 19 2023
Don't worry about it, it has already been rejected and this was one of the reasons why. https://github.com/dlang/DIPs/blob/master/DIPs/rejected/DIP1027.md#final-review
Oct 19 2023
On Thursday, 19 October 2023 at 11:10:47 UTC, Richard (Rikki) Andrew Cattermole wrote:Don't worry about it, it has already been rejected and this was one of the reasons why. https://github.com/dlang/DIPs/blob/master/DIPs/rejected/DIP1027.md#final-reviewI think the simplest solution is to give up on one-size-fits-all. slow"this allocates a string" fast"this creates a fast tuple for meta-programming" Even though the user-facing part is quite different, it would be possible to share much code between the two implementations inside the compiler. obviously slow and fast are placeholder names.
Oct 19 2023
On Thursday, 19 October 2023 at 11:10:47 UTC, Richard (Rikki) Andrew Cattermole wrote:Don't worry about it, it has already been rejected and this was one of the reasons why. https://github.com/dlang/DIPs/blob/master/DIPs/rejected/DIP1027.md#final-reviewI don't think Walter has given up on it :P
Oct 19 2023
On 10/19/2023 4:10 AM, Richard (Rikki) Andrew Cattermole wrote:Don't worry about it, it has already been rejected and this was one of the reasons why. https://github.com/dlang/DIPs/blob/master/DIPs/rejected/DIP1027.md#final-reviewIt doesn't give that as a reason.
Oct 19 2023
On 10/19/2023 3:40 AM, Andrea Fontana wrote:// Example deleteFiles("/tmp/test.txt", "/tmp/old.txt"); deleteFiles(i"/tmp/$dirname/$file"); <-- ooops this will be expanded?It will be: ``` deleteFiles("/tmp/%s/%s", dirname, file); ``` And you'll probably get a message like: "Could not find /tmp/%s/%s"
Oct 19 2023
On Thursday, 19 October 2023 at 23:45:19 UTC, Walter Bright wrote:On 10/19/2023 3:40 AM, Andrea Fontana wrote:You might get a message like: ``` Could not find `/tmp/%s/%s` successfully removed directory and all files under `importantApp` Could not find `tempfile.cache` ``` The point is that it's too easy to match to strings, compile, and do a completely unexpected thing. And yes, that's the major reason why 1027 is so bad. -Steve// Example deleteFiles("/tmp/test.txt", "/tmp/old.txt"); deleteFiles(i"/tmp/$dirname/$file"); <-- ooops this will be expanded?It will be: ``` deleteFiles("/tmp/%s/%s", dirname, file); ``` And you'll probably get a message like: "Could not find /tmp/%s/%s"
Oct 19 2023
On 10/19/2023 6:52 PM, Steven Schveighoffer wrote:The point is that it's too easy to match to strings, compile, and do a completely unexpected thing. And yes, that's the major reason why 1027 is so bad.I don't recall this issue even being discussed in the old review of it. It isn't listed in the review objections for DIP1027. https://github.com/dlang/DIPs/blob/master/DIPs/rejected/DIP1027.md#description If you can point the discussion out to me, I'd appreciate it. But I undestand you don't like this, and there is a rather nice solution. Recall Andrea Fontana's example: ``` void deleteFiles(string[]... files) { ... } ``` As a special case, an i-string will not be a match for `string[]...`. This makes sense, as a function requiring a format string would not be expecting no string. A match would have to be of the form: ``` void deleteFiles(string fmt, ...) { ... } ``` which is the natural form a formatting function would take. If the user wanted to use i-strings to pass to `deleteFiles(string[]...)`, he'd use: ``` string dirname = "project"; string file = "main.o"; deleteFiles(format(i"/tmp/$dirname/$file")); ``` which looks rather nice and self-evident. Hope you like it!
Oct 20 2023
On Friday, 20 October 2023 at 08:03:55 UTC, Walter Bright wrote:On 10/19/2023 6:52 PM, Steven Schveighoffer wrote:What are your main objections to this https://github.com/John-Colvin/YAIDIP[...]I don't recall this issue even being discussed in the old review of it. It isn't listed in the review objections for DIP1027. [...]
Oct 20 2023
On Friday, 20 October 2023 at 13:03:45 UTC, Imperatorn wrote:On Friday, 20 October 2023 at 08:03:55 UTC, Walter Bright wrote:It looks like a good DIP, and as a plus it has an implementation: https://github.com/dlang/dmd/pull/15714 And the DIP is based on prior DIPs and co-written by Andrei. I think it looks reasonable. Please take a second look if possible.On 10/19/2023 6:52 PM, Steven Schveighoffer wrote:What are your main objections to this https://github.com/John-Colvin/YAIDIP[...]I don't recall this issue even being discussed in the old review of it. It isn't listed in the review objections for DIP1027. [...]
Oct 20 2023
On Friday, 20 October 2023 at 08:03:55 UTC, Walter Bright wrote:On 10/19/2023 6:52 PM, Steven Schveighoffer wrote:No it's not listed (which surprises me), and the thread is huge, I don't feel like going through it all. I do remember objecting to it though, on the grounds that you can't overload based on a string. For example, I have in mysql-native a function: ```d ulong exec(T...) (Connection conn, const(char[]) sql, T args) ``` Which accepts the statement in the mysql format of using `?` for placeholders. In order to accept an interpolation tuple, I'd have to name a new function: ```d ulong execi(T...) (Connection conn, const(char[]) sql, T args) ``` Which then forwards to the real `exec`. And there would be no way for the compiler to prevent the user from using either with the incorrect parameters. *AND* the `execi` function needs to parse the format string at runtime replacing "%s" with "?". Whereas, YAIDIP and DIP1036 provide a way for the `exec` function to be overloaded with interpolation literals, and always do the right thing at pretty much no runtime cost (the building of the string can be at compile-time).The point is that it's too easy to match to strings, compile, and do a completely unexpected thing. And yes, that's the major reason why 1027 is so bad.I don't recall this issue even being discussed in the old review of it. It isn't listed in the review objections for DIP1027.But I undestand you don't like this, and there is a rather nice solution. Recall Andrea Fontana's example: ``` void deleteFiles(string[]... files) { ... } ``` As a special case, an i-string will not be a match for `string[]...`. This makes sense, as a function requiring a format string would not be expecting no string. A match would have to be of the form: ``` void deleteFiles(string fmt, ...) { ... } ```Just another whacked mole? What about the Exception problem? ```d throw new Exception(i"Invalid integer value in $file: $val"); ``` -Steve
Oct 20 2023
On 10/20/2023 9:52 AM, Steven Schveighoffer wrote:Just another whacked mole? What about the Exception problem? ```d throw new Exception(i"Invalid integer value in $file: $val"); ```You'll get an exception message: Exception at FILE(LINE): Invalid integer value in %s: %s which is pretty much a nothingburger as a problem. YAIDIP can also call the wrong function if you're not careful to make sure the right one is in scope. YAIDIP is also going to match any template that has a first argument of type T with a weird struct that frankly few users will know exists. Anything that generates tuples is going to have minor issues with overload matching.
Oct 20 2023
On Friday, 20 October 2023 at 19:58:44 UTC, Walter Bright wrote:On 10/20/2023 9:52 AM, Steven Schveighoffer wrote:So you think it's a nothingburger to have zero idea where this exception was thrown from so you can figure it out? e.g. ``` object.Exception foo.txt(18446744073709551574): Invalid integer value in %s: %s ```Just another whacked mole? What about the Exception problem? ```d throw new Exception(i"Invalid integer value in $file: $val"); ```You'll get an exception message: Exception at FILE(LINE): Invalid integer value in %s: %s which is pretty much a nothingburger as a problem.YAIDIP can also call the wrong function if you're not careful to make sure the right one is in scope.Can you explain this? What function needs to be in scope?YAIDIP is also going to match any template that has a first argument of type T with a weird struct that frankly few users will know exists.Yes, and it's possible the compiler can help out here, just like it says `string` instead of `immutable(char)*` -Steve
Oct 20 2023
On Friday, 20 October 2023 at 19:58:44 UTC, Walter Bright wrote:On 10/20/2023 9:52 AM, Steven Schveighoffer wrote:This feels like the kind of thing that "Make illegal states unrepresentable" is supposed to be prevent, no?Just another whacked mole? What about the Exception problem? ```d throw new Exception(i"Invalid integer value in $file: $val"); ```You'll get an exception message: Exception at FILE(LINE): Invalid integer value in %s: %s which is pretty much a nothingburger as a problem.
Oct 20 2023
On Tue, Oct 17, 2023 at 05:37:15PM +0000, Adam D Ruppe via Digitalmars-d wrote: [...]If we want to move forward, there's actually a good proposal out there: https://github.com/John-Colvin/YAIDIPJust read through this. This is one of the better interpolated string DIPs I've seen yet; I'd definitely support this over the dip1027 if John would be willing to formally submit it for DIP review. T -- English is useful because it is a mess. Since English is a mess, it maps well onto the problem space, which is also a mess, which we call reality. Similarly, Perl was designed to be a mess, though in the nicest of all possible ways. -- Larry Wall
Oct 17 2023
On Tuesday, 17 October 2023 at 19:33:13 UTC, H. S. Teoh wrote:Just read through this. This is one of the better interpolated string DIPs I've seen yet; I'd definitely support this over the dip1027 if John would be willing to formally submit it for DIP review.Yeah, this proposal is actually just plain excellent, and the depths of what it enables go well beyond what the text of the document states. It came out of an attempt to solve a real problem John and Andrei were facing, and they listened to what me and Steven had discussed previously. It brings type safety, tuple compatibility, CTFE *and* runtime flexibility, user extensibility, and rich metainfo about each use. It is easy to make this compatible with normal strings, but also html templates, sql queries, gnu gettext, shell commands, even things like assert handlers and detailed exception construction that defers string construction to the end... the list goes on and on. And the implementation is easy too. This is a proposal worthy of D.
Oct 17 2023
I decided to have a go and do my own little proposal. Its a pretty big mesh of things, with one key difference, the notion of a binary-less expression. This simplifies the grammar quite a bit and should do the same for the implementation. https://gist.github.com/rikkimax/90a4b21feabcf34dbecb8efcb587f8e1 ```d stderr.write("$clear\r${white}Progress:$clear$progress% \t${white}Speed:$clear $curSpeed $unit"); ``` It should be familiar to both C++ and Python folk. I've already implemented a formatter read/write for ``{:}`` syntax so I might be a tad biased, especially since I want to use ``$Identifier`` for something (not that it conflicts here).
Oct 17 2023
On Thursday, 12 October 2023 at 13:39:46 UTC, Andrea Fontana wrote:Real life example. Render a string like this: ``` \x1b[2K\r\x1b[1mProgress:\x1b[0m 50% \x1b[1m\tSpeed:\x1b[0m 15.5 KB/s ``` now (error prone and difficult to debug, try to code it!): ``` stderr.write(format("%s\r%sProgress:%s %5.1f%% %s\tSpeed:%s %6.1f %s%s", clear, white, clear, progress, white, clear, curSpeed, unit)); ``` (or with string concat, good luck!) vs: ``` stderr.write("${clear}\r{$white}Progress:${clear}${progress}% \t${white}Speed:${clear} ${curSpeed} ${unit}"); ``` AndreaJust a quick comment. Probably with string interpolation, less is more. So the simplest DIP probably wins. ❤️
Oct 17 2023
On 10/17/2023 10:14 PM, Imperatorn wrote:Just a quick comment. Probably with string interpolation, less is more.Solving for 90% of the cases with a simple solution is preferable than a much more complex one to get a few more %. This is a winning strategy with programming. For example, with Ddoc and Unittest, the idea was to go for a simple-as-possible scheme to cover 90%, and it proved to be a winner.
Oct 18 2023
On Thursday, 19 October 2023 at 01:12:53 UTC, Walter Bright wrote:On 10/17/2023 10:14 PM, Imperatorn wrote:hmmmmm I would think its nonlinear and you could easily justify 90 -> 95% being 2x the complexity costJust a quick comment. Probably with string interpolation, less is more.Solving for 90% of the cases with a simple solution is preferable than a much more complex one to get a few more %. This is a winning strategy with programming. For example, with Ddoc and Unittest, the idea was to go for a simple-as-possible scheme to cover 90%, and it proved to be a winner.
Oct 18 2023
On 10/18/2023 6:42 PM, monkyyy wrote:I would think its nonlinear and you could easily justify 90 -> 95% being 2x the complexity costFor another example, the iphone camera pretty much destroyed the market for standalone cameras other than special purpose ones.
Oct 19 2023
On Thursday, 19 October 2023 at 07:45:44 UTC, Walter Bright wrote:On 10/18/2023 6:42 PM, monkyyy wrote:I didn't misunderstand you I disagree with your numbers and what they implied you were thinking about the tradeoff space. The difference between 90% and 95%, isn't *linear*, 0-1 probalitys are an s-curve, and 90% means it breaks 1 out of 10, 95% means it breaks 1 out of 20, 99% means it breaks 1 out of 100. etc. Given a complexity increase of 2x going from 90% to 95% means on the user's end they will get 1/2 the number of headaches, so I would feel that's a good and realistic trade-off. By all means don't chase 100%, but 95,97,99% different story.I would think its nonlinear and you could easily justify 90 -> 95% being 2x the complexity costFor another example, the iphone camera pretty much destroyed the market for standalone cameras other than special purpose ones.
Oct 19 2023
On Thursday, 19 October 2023 at 01:12:53 UTC, Walter Bright wrote:Solving for 90% of the cases with a simple solution is preferable than a much more complex one to get a few more %. This is a winning strategy with programming.YAIDIP is an incredibly simple solution that has enormous bang for buck. Its implementation is very simple.
Oct 18 2023
On Thursday, 19 October 2023 at 02:48:43 UTC, Adam D Ruppe wrote:On Thursday, 19 October 2023 at 01:12:53 UTC, Walter Bright wrote:I like YAIDIP a lot from what I've read. I also trust Adam and Steve and others in the discord universe who are demonstrated app/template wizards. Me, not so wizardly in that arena so grain of salt advised :-) .Solving for 90% of the cases with a simple solution is preferable than a much more complex one to get a few more %. This is a winning strategy with programming.YAIDIP is an incredibly simple solution that has enormous bang for buck. Its implementation is very simple.
Oct 19 2023
On Thursday, 19 October 2023 at 01:12:53 UTC, Walter Bright wrote:On 10/17/2023 10:14 PM, Imperatorn wrote:AgreedJust a quick comment. Probably with string interpolation, less is more.Solving for 90% of the cases with a simple solution is preferable than a much more complex one to get a few more %. This is a winning strategy with programming. For example, with Ddoc and Unittest, the idea was to go for a simple-as-possible scheme to cover 90%, and it proved to be a winner.
Oct 18 2023
On Thursday, 19 October 2023 at 01:12:53 UTC, Walter Bright wrote:On 10/17/2023 10:14 PM, Imperatorn wrote:Please give us something, anything at all 😭 As long as it's safe and doesn't destroy anything 🙏Just a quick comment. Probably with string interpolation, less is more.Solving for 90% of the cases with a simple solution is preferable than a much more complex one to get a few more %. This is a winning strategy with programming. For example, with Ddoc and Unittest, the idea was to go for a simple-as-possible scheme to cover 90%, and it proved to be a winner.
Oct 19 2023