digitalmars.D - DIP 1027---String Interpolation---Community Review Round 1
- Mike Parker (15/15) Dec 11 2019 This is the feedback thread for the first round of Community
- Walter Bright (4/5) Dec 11 2019 bananas);
- Rumbu (6/9) Dec 11 2019 So we cannot have variables named d, s, f, g, x and so on because
- MrSmith (3/7) Dec 11 2019 According to proposal you would wrap format specifiers into {},
- rumbu (6/13) Dec 11 2019 Nope, that means "use %d format specifier to print number of
- drug (3/10) Dec 11 2019 According to the DIP this is valid. It would be interpreted as
- Patrick Schluter (18/32) Dec 11 2019 No. Read the grammar. Format specifiers MUST be in {}.
- Alexandru Ermicioi (14/29) Dec 11 2019 Why not just split interpolated string into just a tuple of args
- MrSmith (4/10) Dec 11 2019 That's an option, but one would also need to figure out handling
- Alexandru Ermicioi (19/29) Dec 11 2019 Do we really need support for format specifiers which are mostly
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (15/24) Dec 11 2019 Agree. Your suggestion is much more in line with metaprogramming
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (10/13) Dec 11 2019 Actually, make that a tuple, but add proper tuples first. So that
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (4/8) Dec 11 2019 Note: the above suggestion is close to Python 3.
- Adam D. Ruppe (7/9) Dec 11 2019 But then it is impossible to tell which parts were in the string
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (23/31) Dec 11 2019 Can't you handle this by taking the head of the tuple and then
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (6/10) Dec 11 2019 You could use «,» to indicate a formatter like this:
- jmh530 (30/34) Dec 11 2019 Python has f interpolation that looks like
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (6/9) Dec 11 2019 Yes, I no longer use % in Python. It is baggage. I either use
- jmh530 (8/14) Dec 11 2019 Please see my reply above to bachmeier on Python's format strings
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (18/22) Dec 11 2019 Sure, but as I pointed out you can do both. Just upgrade "%d" and
- Patrick Schluter (5/20) Dec 11 2019 This wouldn't work for C formats like printf. The proposition has
- Alexandru Ermicioi (10/35) Dec 11 2019 Indeed it doesn't, yet it falls nicely with std.conv.text, and
- Walter Bright (2/5) Dec 13 2019 It definitely needs to work for printf and writef.
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (4/5) Dec 14 2019 That's an odd requirement, considering you can update writef with
- Walter Bright (2/7) Dec 13 2019 I don't see the point of that. The user could write it that way to begin...
- Steven Schveighoffer (8/18) Dec 14 2019 Walter, this is literally the point of string interpolation. A similar
- Walter Bright (11/26) Dec 14 2019 "I ate ",
- Alexandru Ermicioi (24/33) Dec 14 2019 Yes he could. The main concern I have is that current proposal is
- Nick Treleaven (8/10) Dec 16 2019 Translations. Marking all your sentence fragments as translatable
- Sebastiaan Koppe (10/13) Dec 11 2019 Nice!
- Martin Tschierschke (7/22) Dec 11 2019 Yes +1! It should be something common, not a dlang only syntax.
- bachmeier (4/9) Dec 11 2019 My recollection is that in Python 3 that would be done {fvar:
- jmh530 (6/9) Dec 11 2019 Python's formatting is described here:
- Walter Bright (4/7) Dec 13 2019 Both these have parsing problems.
- Walter Bright (4/6) Dec 13 2019 Unfortunately, there is enough variation in common use that there's no s...
- bachmeier (5/9) Dec 11 2019 That's definitely not bikeshedding. Given how late D is to the
- Walter Bright (4/9) Dec 13 2019 The interpolation string needs to be a separate token. But I was thinkin...
- Andrea Fontana (8/23) Dec 11 2019 Nice but it sounds a bit "hacky" to me.
- Andrea Fontana (3/4) Dec 11 2019 Oops, I mean "Hello %sworld123"
- Andre Pany (10/42) Dec 11 2019 If my understanding is right, string assignment is not supported
- Adam D. Ruppe (3/4) Dec 11 2019 No, it can be passed to anything. std.string.format does it
- Andrea Fontana (4/12) Dec 11 2019 Probably we're going to add format everywhere write:
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (13/15) Dec 11 2019 Or maybe some kind of formatting-objects protocol? Then you could
- Walter Bright (3/4) Dec 13 2019 Functions currently can't return tuples, meaning you couldn't make it wo...
- Rumbu (2/6) Dec 11 2019 What if I don't want any space after %apples?
- Adam D. Ruppe (3/5) Dec 11 2019 i"I ate %(apples)and "
- Walter Bright (2/3) Dec 13 2019 Note that this is similar to how text macros work in the make program.
- Patrick Schluter (2/11) Dec 11 2019 Then you write %(apples)nospace.
- Ernesto Castellotti (8/23) Dec 11 2019 From the dip it seems that it is only valid for writefln & co
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (13/16) Dec 11 2019 The problem is making it work with something like a
- Alexandru Ermicioi (14/46) Dec 11 2019 this code should be valid although it wont be a string but a
- Patrick Schluter (5/15) Dec 11 2019 It is allowed everywhere where a tuple expression is allowed
- Meta (9/22) Dec 11 2019 It works already (un?)fortunately:
- Ernesto Castellotti (6/32) Dec 11 2019 Yes this is the purpose of the dip, but it is not what I expect
- Walter Bright (2/4) Dec 13 2019 You're right. That's really all it does. It will work anywhere a tuple w...
- Sebastiaan Koppe (8/11) Dec 11 2019 What happens in a template?
- Walter Bright (3/11) Dec 13 2019 As if you wrote:
- Patrick Schluter (20/20) Dec 11 2019 On Wednesday, 11 December 2019 at 09:52:21 UTC, Mike Parker wrote:
- Walter Bright (5/6) Dec 14 2019 You're quite right. I missed that. With some noodling about with this pr...
- Bastiaan Veelo (4/8) Dec 14 2019 Nice. It’s also more like what several other languages do.
- Anonymouse (11/15) Dec 11 2019 This is amazing and I would use it straight away.
- Walter Bright (5/14) Dec 14 2019 Not going to use positional specifiers:
- Robert Schadek (31/31) Dec 11 2019 I'm not really sure if the balance of added complexity vs. payoff
- Meta (8/39) Dec 11 2019 It can *almost* already be done with templates:
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (3/7) Dec 11 2019 Maybe "mixin" could be a return type requiring CTFE and
- Meta (20/27) Dec 11 2019 Yeah, I think if it comes down to adding a new language feature
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (5/8) Dec 11 2019 Could one option be to use another symbol than «!» and make it
- Bastiaan Veelo (5/13) Dec 11 2019 I like this. A universal improvement that also happens to enable
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (8/13) Dec 11 2019 Another option is to add unicode support:
- Ernesto Castellotti (2/23) Dec 11 2019 This would be really cool
- Paul Backus (9/28) Dec 11 2019 One idea I've seen floated in a previous thread is to introduce a
- Walter Bright (2/3) Dec 14 2019 I tried that (the enum in template trick). It's close, but still no bana...
- Patrick Schluter (27/57) Dec 11 2019 Disagree. This proposition strikes exactly the right balance
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (11/20) Dec 11 2019 If something is bad… (…and I agree, printf is not good.) Why
- Robert burner Schadek (14/59) Dec 11 2019 Not at all, before I was trying to do to much.
- Walter Bright (6/10) Dec 14 2019 I tried. It just doesn't get us there without some awkward syntax.
- H. S. Teoh (43/47) Dec 11 2019 [...]
- Walter Bright (11/18) Dec 14 2019 No. The trouble happens with how semantic analysis is done - leaves firs...
- Jacob Carlborg (4/16) Dec 14 2019 Implicit string concatenation is deprecated and gives an error.
- Walter Bright (4/5) Dec 14 2019 I know. But i strings aren't string literals, and this would be special ...
- Steven Schveighoffer (14/38) Dec 14 2019 What if the strings are all interpolated strings? e.g.:
- Walter Bright (9/19) Dec 14 2019 Then you'll get a tuple that looks like:
- Steven Schveighoffer (29/52) Dec 16 2019 Why? I mean concatenation of Tuples isn't defined to do anything.
- Walter Bright (12/27) Dec 17 2019 I did concatenate the tuples in the most obvious manner - concatenating ...
- Alexandru Ermicioi (6/10) Dec 17 2019 Well they would be a tremendous addition for metaprogramming
- Meta (5/27) Dec 14 2019 One thing to note is that if string interpolation returns a
- Steven Schveighoffer (46/68) Dec 11 2019 First, I like the concept. It fixes the issue of "which parameters are
- Andrea Fontana (3/12) Dec 11 2019 query(i"select * from sometable where date < %someDate".format);
- Steven Schveighoffer (10/28) Dec 11 2019 https://en.wikipedia.org/wiki/SQL_injection
- H. S. Teoh (30/47) Dec 11 2019 [...]
- Steven Schveighoffer (6/40) Dec 11 2019 OK, this is definitely a winner, way better than my idea. Only thing
- Steven Schveighoffer (7/10) Dec 11 2019 Hm... heredoc gives us a precedent that might be valuable here.
- =?iso-8859-1?Q?Robert_M._M=FCnch?= (16/32) Dec 13 2019 Yes, much better to reduce syntax-cluttering. Why not lean towards
- Walter Bright (2/13) Dec 14 2019 Too complex for too little gain.
- Bastiaan Veelo (8/39) Dec 11 2019 […]
- Bastiaan Veelo (3/5) Dec 11 2019 Seems I’m mixing up template and string mixins.
- Walter Bright (3/5) Dec 14 2019 Since that would require some extra syntax for each i string literal, it...
- Steven Schveighoffer (25/32) Dec 14 2019 It doesn't actually
- Walter Bright (3/4) Dec 14 2019 It wouldn't be used enough to make it worthwhile. The extra syntax neces...
- Walter Bright (2/16) Dec 14 2019 I agree, except don't need the extra ( ).
- Walter Bright (18/39) Dec 14 2019 It's a great point. I propose a modification:
- Steven Schveighoffer (4/12) Dec 14 2019 Thanks! That's much better
- mipri (68/71) Dec 11 2019 Questions for the rationale:
- mipri (54/60) Dec 11 2019 I think there's a general rule here:
- Ola Fosheim Grostad (4/9) Dec 12 2019 Yes, the requirement should be that it has been implemented as a
- aliak (7/11) Dec 12 2019 That is a really good point! But, what about token strings?
- Adam D. Ruppe (17/20) Dec 12 2019 This could be an innovative feature.
- aliak (3/6) Dec 12 2019 Except you can actually assign it to a string?
- H. S. Teoh (7/13) Dec 12 2019 [...]
- aliak (6/19) Dec 12 2019 So i"blah %var" would not return a tuple but a type that has
- Adam D. Ruppe (11/13) Dec 12 2019 Yup that's my proposal:
- Andrea Fontana (4/9) Dec 13 2019 Quite better solution in my opinion.
- Ernesto Castellotti (2/12) Dec 13 2019 Yes, I would also like a dip with the Adam proposal
- aliak (5/18) Dec 16 2019 Ah ok. Yeah that sounds pretty good!
- H. S. Teoh (6/8) Dec 16 2019 For generating injection-proof SQL, for one thing. Probably others.
- Adam D. Ruppe (29/30) Dec 12 2019 The javascript version is allowed to return whatever it wants.
- Atila Neves (4/10) Dec 12 2019 It'd be great if you could expand on this with a list of examples
- Petar Kirov [ZombineDev] (56/68) Dec 12 2019 Tagged template literals are indeed quite nice in JS. Here's an
- mipri (53/92) Dec 12 2019 With no changes to DIP-1027:
- mipri (64/70) Dec 12 2019 To be clear, some cool stuff is
- Adam D. Ruppe (51/53) Dec 12 2019 Of course, there's the examples of printf, writeln, sql query..
- mipri (9/17) Dec 12 2019 This doesn't work though:
- Adam D. Ruppe (41/46) Dec 12 2019 Indeed, but it does work to pass seq!(() => n). That's why I've
- Timon Gehr (6/17) Dec 12 2019 I think that's a bit hacky, e.g.:
- Adam D. Ruppe (4/5) Dec 12 2019 yeah, can fix that with a lazily initialized cache.
- Sebastiaan Koppe (13/34) Dec 12 2019 That is a good observation. I forgot all about tagged template
- Walter Bright (4/4) Dec 14 2019 I find your proposal a little confusing. By turning the string into an o...
- Jacob Carlborg (5/7) Dec 14 2019 One would need to explicitly call `toString` or add an `alias this` to
- Adam D. Ruppe (26/31) Dec 14 2019 Right, not directly. But then it is trivial to add a member of
- Steven Schveighoffer (25/60) Dec 14 2019 But did what you asked? Coding is full of such dilemmas. I've actually
- Adam D. Ruppe (24/33) Dec 14 2019 The grouping of the items in the string. Tuples auto-flatten and
- Walter Bright (8/16) Dec 14 2019 I was afraid that would be it. The extra syntax kills it, along with the...
- Adam D. Ruppe (29/33) Dec 14 2019 This is true, but ONLY for the printf case. It just works in all
- Walter Bright (10/47) Dec 14 2019 printf is a very important case, and it kills it for scanf and every oth...
- Jab (13/29) Dec 14 2019 IIRC you said dmd was just a direct translation from C and
- Guillaume Piolat (5/7) Dec 15 2019 That's wrong, we use printf snprint and sprintf a lot since we
- Jab (7/15) Dec 15 2019 It was a figure of speech. You are most definitely in the
- Aliak (8/10) Dec 15 2019 To use it people will need to understand how to use d tuples as
- Walter Bright (2/3) Dec 15 2019 No, they don't.
- aliak (4/8) Dec 16 2019 User: why can't I do this?/Why doesn't this work?
- Patrick Schluter (21/31) Dec 16 2019 because
- Patrick Schluter (22/27) Dec 16 2019 Maybe I'm wrong here, I haven't thought it through, but in first
- Jacob Carlborg (8/28) Dec 16 2019 Not sure how other languages do it but in Ruby the interpolation
- Patrick Schluter (19/54) Dec 16 2019 Yes, probably. The issue I had with the transformation as string
- Jacob Carlborg (21/40) Dec 17 2019 It's difficult to say as your code doesn't compile. As it's
- Patrick Schluter (29/77) Dec 17 2019 Yes, and that was the point of the exercice. Transforming the
- Jacob Carlborg (8/44) Dec 17 2019 I don't see how lowering to a tuple will change anything. It's not
- Patrick Schluter (9/53) Dec 17 2019 Which was my point. An interpolated string cannot be stored in a
- Steven Schveighoffer (17/54) Dec 17 2019 Wow, I don't think that the first item can be done with the DIP. But
- ag0aep6g (2/18) Dec 17 2019 alias as = AliasSeq!("%s apples and %s bananas", apples, bananas);
- Steven Schveighoffer (17/22) Dec 17 2019 :facepalm:
- Meta (7/32) Dec 17 2019 This got me excited, but unfortunately it doesn't work with
- Steven Schveighoffer (8/21) Dec 17 2019 Right, the alias has to be a symbol or a constant. Though you could
- Alexandru Ermicioi (5/10) Dec 17 2019 tuple of lazy args should work probably (i.e. pass through vararg
- aliak (6/16) Dec 17 2019 I'm pretty sure I said that I expect interpolated strings to be
- Patrick Schluter (4/21) Dec 18 2019 The question is, what is that string supposed to contain. The
- Alexandru Ermicioi (17/46) Dec 17 2019 Well there is a issue in javascript, interpolated string are
- aliak (7/30) Dec 16 2019 Exactly. And then explain why. And what is that thing on the
- Patrick Schluter (16/50) Dec 16 2019 Not true for some languages I checked
- Patrick Schluter (4/9) Dec 16 2019 Ignore that random crap at the end of my post. It was a copy
- aliak (13/32) Dec 16 2019 You can assign strings to interpolated strings in all these
- Atila Neves (3/13) Dec 16 2019 import std.format: format;
- Nick Treleaven (15/23) Dec 16 2019 That isn't an answer to the question, it's just a workaround.
- Walter Bright (14/39) Dec 16 2019 Having it go directly to a string has multiple problems:
- Jacob Carlborg (18/34) Dec 17 2019 It doesn't need to go directly to a string. Just the end result
- Jacob Carlborg (6/21) Dec 17 2019 With this implementation SwiftUI supports internationalization of
- Nick Treleaven (46/80) Dec 17 2019 I said implicitly convert. If it lowers to a templated struct, it
- aliak (2/18) Dec 16 2019 This is non obvious. And only explainable by mentioning tuples.
- Alexandru Ermicioi (11/13) Dec 15 2019 A bit other topic, but this can be fixed by splitting object.d in
- rikki cattermole (2/18) Dec 15 2019 Yes please.
- Walter Bright (5/17) Dec 16 2019 The reality is that compilation time is more proportional to the number ...
- Alexandru Ermicioi (9/30) Dec 17 2019 I doubt someone will complain, about splitting object module into
- Walter Bright (3/8) Dec 20 2019 People often complain as DMD's compile speed steadily deteriorates. A fe...
- Andre Pany (8/9) Dec 15 2019 This is for me the most important thing for string interpolation.
- Guillaume Piolat (4/12) Dec 15 2019 Careful that if that happens, then it may be another feature that
- Jab (11/26) Dec 15 2019 There's no reason it can't be implicitly converted to a string.
- Adam D. Ruppe (6/8) Dec 15 2019 D's writef uses it too, as well as std.format. Do do the vibe
- mipri (16/22) Dec 15 2019 Which brings this to mind:
- Adam D. Ruppe (4/7) Dec 15 2019 I actually think that is a cool feature of the proposal. (though
- Walter Bright (2/4) Dec 15 2019 It works with scanf, too, though I never use scanf.
- Jab (10/20) Dec 15 2019 This is going to add a feature to the language that is dependent
- Adam D. Ruppe (5/6) Dec 15 2019 writef is neither printf nor does it use sprintf to implement it
- Jab (2/3) Dec 15 2019 Exactly.
- Guillaume Piolat (8/10) Dec 15 2019 Okay. Let's say this would compile:
- Jab (10/21) Dec 15 2019 "Implicitly converted" meaning it exists as something else and
- Adam D. Ruppe (13/15) Dec 15 2019 That's exactly what mine would do.
- Guillaume Piolat (4/9) Dec 15 2019 On second thought, it's true interpolated string are most wanted
- Seb (10/24) Dec 15 2019 I highly doubt that modern D applications use printf enough that
- Walter Bright (2/5) Dec 13 2019 I'm not sure what you expect that to do?
- mipri (16/21) Dec 13 2019 Complete example:
- aliak (26/41) Dec 11 2019 1. The DIP fails to mention why this has been chosen as better
- Jonathan Marler (40/55) Dec 11 2019 Lowering interpolated strings to a format string and a tuple of
- Martin Tschierschke (9/11) Dec 12 2019 On Thursday, 12 December 2019 at 05:07:44 UTC, Jonathan Marler
- Steven Schveighoffer (36/75) Dec 12 2019 Indeed, one can potentially have more use cases than format string plus
- Walter Bright (2/3) Dec 14 2019 Indeed that is my fault and I'll fix that.
- Jacob Carlborg (39/41) Dec 13 2019 In my opinion, the semantics of string interpolation need to
- Walter Bright (7/39) Dec 14 2019 It only makes sense if foo is an expression.
- Jacob Carlborg (5/6) Dec 14 2019 Yes, I understand that. I don't think it's a good idea. I wrote how I
- Tim (37/40) Dec 14 2019 If a special type is used for the format string after lowering,
- Guillaume Piolat (3/6) Dec 15 2019 I like this proposal.
- Walter Bright (3/3) Dec 16 2019 Some hashtags to get things started:
- Steven Schveighoffer (9/31) Dec 16 2019 Might I suggest we come up with a new name for this technique? I see
- mipri (16/25) Dec 16 2019 Programming language terminology is so random already that
- Patrick Schluter (9/38) Dec 16 2019 The issue with user expectations should not be holding up on what
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (12/15) Dec 16 2019 Not sure what you mean by this, I find popular languages to be
- mipri (41/44) Dec 16 2019 Here's some prose that I'd expect in a FAQ or tutorial.
- Jab (26/59) Dec 16 2019 This would push the complexity onto the query implementation. As
- mipri (27/47) Dec 16 2019 What?
- Walter Bright (2/3) Dec 17 2019 Your response is well-written with good arguments, but please leave off ...
- mipri (2/6) Dec 17 2019 Sure. I thought that was too much, as well.
- Jab (18/64) Dec 17 2019 Sorry I forgot to go back and edit this after I changed it. It be
- H. S. Teoh (9/14) Dec 17 2019 [...]
- Walter Bright (2/4) Dec 17 2019 Thank you, this is good stuff!
- Jacob Carlborg (11/18) Dec 17 2019 I think the name "associative array" is pretty good because I
- Steven Schveighoffer (9/31) Dec 17 2019 BTW, people have been talking about usage like:
- Atila Neves (4/14) Dec 18 2019 Huh. I wrote my example without UFCS precisely because I didn't
- jmh530 (12/21) Dec 18 2019 I think it works because format takes a variadic template as an
- Steven Schveighoffer (7/34) Dec 18 2019 Nope. Not just variadic templates:
- jmh530 (3/10) Dec 18 2019 Interesting.
- Mike Parker (6/22) Dec 18 2019 Please keep comments in this thread focused on the DIP. I've got
- Steven Schveighoffer (8/14) Dec 18 2019 It's somewhat relevant because the usage case for tagging interpolated
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (20/24) Dec 20 2019 So here is a general response:
- Petar Kirov [ZombineDev] (6/14) Dec 18 2019 I introduce you to a D library I was working on a couple of years
- mipri (8/11) Dec 19 2019 How are the following strings handled?
- aberba (5/22) Dec 26 2019 Is there a reason it's not $ instead of %? String interpolation
- Patrick Schluter (4/12) Dec 26 2019 If you read in the thread, Walter accepted the change to $
- Mike Parker (4/7) Dec 26 2019 He updated it last week:
- Jab (12/31) Dec 26 2019 an integer as a floating point value. The meaning of the format
- Mike Parker (6/9) Dec 26 2019 Please save further feedback for the next review round. This
This is the feedback thread for the first round of Community Review for DIP 1027, "String Interpolation": https://github.com/dlang/DIPs/blob/148001a963f5d6e090bb6beef5caf9854372d0bc/DIPs/DIP1027.md All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on December 25, or when I make a post declaring it complete. At the end of Round 1, if further review is deemed necessary, the DIP will be scheduled for another round of Community Review. Otherwise, it will be queued for the Final Review and Formal Assessment. Anyone intending to post feedback in this thread is expected to be familiar with the reviewer guidelines: https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md *Please stay on topic!* Thanks in advance to all who participate.
Dec 11 2019
printf("I ate %s and %d totalling %s fruit.\n", apples, bananas, apples +bananas); Gaah, that should be: printf("I ate %d and %d totalling %d fruit.\n", apples, bananas, apples + bananas);
Dec 11 2019
On Wednesday, 11 December 2019 at 09:52:21 UTC, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1027, "String Interpolation": https://github.com/dlang/DIPs/blob/148001a963f5d6e090bb6beef5caf9854372d0bc/DIPs/DIP1027.mdSo we cannot have variables named d, s, f, g, x and so on because they are standard format specifiers. What happens with custom format specifiers, any one letter variable cannot be interpolated? Why reinvent the wheel and not adopt the common wisdom of {var}
Dec 11 2019
On Wednesday, 11 December 2019 at 10:48:56 UTC, Rumbu wrote:So we cannot have variables named d, s, f, g, x and so on because they are standard format specifiers. What happens with custom format specifiers, any one letter variable cannot be interpolated?According to proposal you would wrap format specifiers into {}, like i"%{d}bananas"
Dec 11 2019
On Wednesday, 11 December 2019 at 11:00:12 UTC, MrSmith wrote:On Wednesday, 11 December 2019 at 10:48:56 UTC, Rumbu wrote:Nope, that means "use %d format specifier to print number of bananas". According to the DIP, this is invalid: string what = "bread"; int d = 10; writefln(i"making %what using %d ingredients");So we cannot have variables named d, s, f, g, x and so on because they are standard format specifiers. What happens with custom format specifiers, any one letter variable cannot be interpolated?According to proposal you would wrap format specifiers into {}, like i"%{d}bananas"
Dec 11 2019
On 12/11/19 2:35 PM, rumbu wrote:Nope, that means "use %d format specifier to print number of bananas". According to the DIP, this is invalid: string what = "bread"; int d = 10; writefln(i"making %what using %d ingredients");According to the DIP this is valid. It would be interpreted as writefln("making %s using %s ingredients", what, d);
Dec 11 2019
On Wednesday, 11 December 2019 at 11:35:05 UTC, rumbu wrote:On Wednesday, 11 December 2019 at 11:00:12 UTC, MrSmith wrote:No. Read the grammar. Format specifiers MUST be in {}. Element: Character '%%' '%' Argument '%' FormatString Argument FormatString: '{' FormatString '}' CharacterNoBraces CharacterNoBraces: CharacterNoBrace CharacterNoBrace CharacterNoBraces CharacterNoBrace: characters excluding '{' and '}' characters does not exclude s, d, f, g etc.On Wednesday, 11 December 2019 at 10:48:56 UTC, Rumbu wrote:Nope, that means "use %d format specifier to print number of bananas". According to the DIP, this is invalid:So we cannot have variables named d, s, f, g, x and so on because they are standard format specifiers. What happens with custom format specifiers, any one letter variable cannot be interpolated?According to proposal you would wrap format specifiers into {}, like i"%{d}bananas"string what = "bread"; int d = 10; writefln(i"making %what using %d ingredients");which is transformed in writefln("making %s using %s ingredients", what, d);
Dec 11 2019
On Wednesday, 11 December 2019 at 09:52:21 UTC, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1027, "String Interpolation": https://github.com/dlang/DIPs/blob/148001a963f5d6e090bb6beef5caf9854372d0bc/DIPs/DIP1027.md All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on December 25, or when I make a post declaring it complete. At the end of Round 1, if further review is deemed necessary, the DIP will be scheduled for another round of Community Review. Otherwise, it will be queued for the Final Review and Formal Assessment. Anyone intending to post feedback in this thread is expected to be familiar with the reviewer guidelines: https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md *Please stay on topic!* Thanks in advance to all who participate.Why not just split interpolated string into just a tuple of args & strings. For example: Given: (i"I ate %apples and %bananas totalling %(apples + bananas) fruit.") Is lowered to a tuple: ("I ate ", apples, " and ", bananas," totalling ", apples + bananas," fruit.") It seems current version unnecessarily ties to printf formatting syntax, and makes harder for them to be used in custom user code. Also user still needs call a function to get assembled string which differs from what other languages are doing with interpolated strings. Best regards, Alexandru.
Dec 11 2019
On Wednesday, 11 December 2019 at 10:57:13 UTC, Alexandru Ermicioi wrote:Why not just split interpolated string into just a tuple of args & strings. For example: Given: (i"I ate %apples and %bananas totalling %(apples + bananas) fruit.") Is lowered to a tuple: ("I ate ", apples, " and ", bananas," totalling ", apples + bananas," fruit.")That's an option, but one would also need to figure out handling of format specifiers
Dec 11 2019
On Wednesday, 11 December 2019 at 11:01:58 UTC, MrSmith wrote:On Wednesday, 11 December 2019 at 10:57:13 UTC, Alexandru Ermicioi wrote:Do we really need support for format specifiers which are mostly appliable for primitive numeric type? I doubt existing format specifiers could be used with structs, classes, or any aggregate structures. An alternative to specifiers we could define free functions that would format numeric values as needed allowing us to write smth like: i"I ate %apples and %bananas totalling %(apples + bananas).format(formatargs))" then, accepting function wouldn't require to meddle with specific printf semantics, and will get properly pre-formatted data to process. if format specifiers are still desired they could be passed as separate arguments similar how it is done for getopts, and then accepting function would need to treat them in context of passed args. Best regards, Alexandru.Why not just split interpolated string into just a tuple of args & strings. For example: Given: (i"I ate %apples and %bananas totalling %(apples + bananas) fruit.") Is lowered to a tuple: ("I ate ", apples, " and ", bananas," totalling ", apples + bananas," fruit.")That's an option, but one would also need to figure out handling of format specifiers
Dec 11 2019
On Wednesday, 11 December 2019 at 10:57:13 UTC, Alexandru Ermicioi wrote:Why not just split interpolated string into just a tuple of args & strings. For example: Given: (i"I ate %apples and %bananas totalling %(apples + bananas) fruit.") Is lowered to a tuple: ("I ate ", apples, " and ", bananas," totalling ", apples + bananas," fruit.") It seems current version unnecessarily ties to printf formatting syntax, and makes harder for them to be used in custom user code.Agree. Your suggestion is much more in line with metaprogramming and offers the right flexibility. Although I think you should just use braces. Also, change the prefix to "f", so that is is similar to other languages like Python. So you could get: log(f"I have {dec(3,2)}{account.total} USD in my pocket") Becomes log("I have ", dec(3,2), account.total," USD in my pocket") That way people can use modern custom formatters if the called function knows how to deal with it. printf is archaic and hardcoding it into the language just makes the language stuck.
Dec 11 2019
On Wednesday, 11 December 2019 at 11:21:08 UTC, Ola Fosheim Grøstad wrote:log(f"I have {dec(3,2)}{account.total} USD in my pocket") Becomes log("I have ", dec(3,2), account.total," USD in my pocket")Actually, make that a tuple, but add proper tuples first. So that you can write log("Vector {vec_formatter(3,2)}{myvec} is ready.", log_channel) and it becomes log (〈"Vector ", vec_formatter(3,2), myvec, " is ready."〉, log_channel ) Where «〈» and «〉» signifies the language-builtin tuple.
Dec 11 2019
On Wednesday, 11 December 2019 at 11:40:44 UTC, Ola Fosheim Grøstad wrote:On Wednesday, 11 December 2019 at 11:21:08 UTC, Ola Fosheim Grøstad wrote:Note: the above suggestion is close to Python 3. https://docs.python.org/3/reference/lexical_analysis.html#formatted-string-literalslog(f"I have {dec(3,2)}{account.total} USD in my pocket")
Dec 11 2019
On Wednesday, 11 December 2019 at 11:21:08 UTC, Ola Fosheim Grøstad wrote:Agree. Your suggestion is much more in line with metaprogramming and offers the right flexibility.But then it is impossible to tell which parts were in the string literal and which parts are outside data. If you are going to do the tuple thing it absolutely must put a string in every other slot so this can be predicted. Walter's proposal at least separates them cleanly.
Dec 11 2019
On Wednesday, 11 December 2019 at 13:43:48 UTC, Adam D. Ruppe wrote:On Wednesday, 11 December 2019 at 11:21:08 UTC, Ola Fosheim Grøstad wrote:Can't you handle this by taking the head of the tuple and then let the formatter absorb what it needs? Then continue with the rest of the tuple? Anyway, that was just a suggestion for making something that was close enough to Python 3 to be easy to use for simple cases (but slightly more difficult for advanced meta programming). No problem with clever tricks in libraries, but it should not be complex on the surface, like this DIP. D needs to 1. embrace metaprogramming and 2. provide a simple surface for newbies.Agree. Your suggestion is much more in line with metaprogramming and offers the right flexibility.But then it is impossible to tell which parts were in the string literal and which parts are outside data.If you are going to do the tuple thing it absolutely must put a string in every other slot so this can be predicted.Not necessarily, if you have a protocol then you can identify the type. However, it is probably better to let the formatting object wrap the data. If you want it simple: add tuples. You either get something that can be turned into a string or you get a tuple, if you get a tuple then the first item in the tuple is a formatter and the rest is data. Probably 100 ways to do this, but the key is to support custom formatters in an efficient manner that does not require high level allocation optimizations (GC languages can optimize away allocations because they control the allocator and all allocations).
Dec 11 2019
On Wednesday, 11 December 2019 at 13:57:20 UTC, Ola Fosheim Grøstad wrote:If you want it simple: add tuples. You either get something that can be turned into a string or you get a tuple, if you get a tuple then the first item in the tuple is a formatter and the rest is data.You could use «,» to indicate a formatter like this: f"This is {"my money"}: {dec(3,2), my_account}!" => ("This is ", "my money", ": ", ( dec(3,2), my_account ), "!")
Dec 11 2019
On Wednesday, 11 December 2019 at 11:21:08 UTC, Ola Fosheim Grøstad wrote:[snip] Also, change the prefix to "f", so that is is similar to other languages like Python. [snip]Python has f interpolation that looks like print(f'Hello {name}! This is {program}') but it also has % formatting that looks like print(‘Hello %(name)s! This is %(program)s.’%(name,program)) This %(name) is probably the closest that compares to this DIP, but it seems like the Python 3.6 string interpolation was meant to replace that. Scala also has f interpolation, but they also have s and raw interpolation. The f is like println(f"$name%s is $height%2.2f meters tall") the s is like println(s"Hello, $name") and the raw is like raw"a\nb" The raw strings would correspond to D's r strings. However, from that string interpolation page from wikipedia, I'm not seeing a lot of other examples of languages that use the f. Many of the languages on there do not require a prefix, though it seems to be mostly dynamic languages. It looks to me like most of use a $ interpolation as in Console.WriteLine($"Hello, {name}") It looks most common to use $var, ${var}, ${expression}, or a little more rarely just {var}. I like Scala's syntax, but you could probably bring together the f and s strings by just providing a default if there is no format provided.
Dec 11 2019
On Wednesday, 11 December 2019 at 14:41:39 UTC, jmh530 wrote:This %(name) is probably the closest that compares to this DIP, but it seems like the Python 3.6 string interpolation was meant to replace that.Yes, I no longer use % in Python. It is baggage. I either use format or f"…". A good reason to aim for modern Python is that newbies will know it. Python is taught in universities... It will look familiar to the next batch of programmers.
Dec 11 2019
On Wednesday, 11 December 2019 at 14:59:27 UTC, Ola Fosheim Grøstad wrote:[snip] Yes, I no longer use % in Python. It is baggage. I either use format or f"…". A good reason to aim for modern Python is that newbies will know it. Python is taught in universities... It will look familiar to the next batch of programmers.Please see my reply above to bachmeier on Python's format strings versus Scala's. Because of the formatting options, I wouldn't lean too heavily on Python's syntax. I think we should look to what other languages do, but ultimately do what is right for D and consistent with the language that is already there.
Dec 11 2019
On Wednesday, 11 December 2019 at 15:13:20 UTC, jmh530 wrote:Because of the formatting options, I wouldn't lean too heavily on Python's syntax. I think we should look to what other languages do, but ultimately do what is right for D and consistent with the language that is already there.Sure, but as I pointed out you can do both. Just upgrade "%d" and "%f" to formatting objects and rewrite them. So, if you want oldstyle you just write f"%...d{variablename}" and it will be turned into f"{std.formatter.format_d(…), variablename}" Having formatting objects is important for many reasons, one is localization. You need that for float and ints. "3,14" vs "3.14" or "1,000,000" vs "1'000'000" etc. So you can do: auto d = some_custom_formatter(…) f"{d, variablename}...{d, somothervariable}" *shrug* printf style is only useful for logging and text file formats. It does not work for GUIs or anything that is user facing. You need to be able to customize and provide your own formatters. (Just think currency "100 USD" vs "100 SEK")
Dec 11 2019
On Wednesday, 11 December 2019 at 10:57:13 UTC, Alexandru Ermicioi wrote:On Wednesday, 11 December 2019 at 09:52:21 UTC, Mike Parker wrote:This wouldn't work for C formats like printf. The proposition has the nice property of being usable for DasBetterC and interfacing with C libraries that use format specifiers (libxml2 anyone?).[...]Why not just split interpolated string into just a tuple of args & strings. For example: Given: (i"I ate %apples and %bananas totalling %(apples + bananas) fruit.") Is lowered to a tuple: ("I ate ", apples, " and ", bananas," totalling ", apples + bananas," fruit.") It seems current version unnecessarily ties to printf formatting syntax, and makes harder for them to be used in custom user code. Also user still needs call a function to get assembled string which differs from what other languages are doing with interpolated strings.
Dec 11 2019
On Wednesday, 11 December 2019 at 15:41:56 UTC, Patrick Schluter wrote:On Wednesday, 11 December 2019 at 10:57:13 UTC, Alexandru Ermicioi wrote:Indeed it doesn't, yet it falls nicely with std.conv.text, and variadic args versions of writeln, has less development overhead (no need to parse string for printf placeholders) when writing functions accepting resulting tuple from interpolation string, and could be made compatible with betterC mode by having a util func that transforms tuple to printf compliant version. Best regards, Alexandru.On Wednesday, 11 December 2019 at 09:52:21 UTC, Mike Parker wrote:This wouldn't work for C formats like printf. The proposition has the nice property of being usable for DasBetterC and interfacing with C libraries that use format specifiers (libxml2 anyone?).[...]Why not just split interpolated string into just a tuple of args & strings. For example: Given: (i"I ate %apples and %bananas totalling %(apples + bananas) fruit.") Is lowered to a tuple: ("I ate ", apples, " and ", bananas," totalling ", apples + bananas," fruit.") It seems current version unnecessarily ties to printf formatting syntax, and makes harder for them to be used in custom user code. Also user still needs call a function to get assembled string which differs from what other languages are doing with interpolated strings.
Dec 11 2019
On 12/11/2019 7:41 AM, Patrick Schluter wrote:This wouldn't work for C formats like printf. The proposition has the nice property of being usable for DasBetterC and interfacing with C libraries that use format specifiers (libxml2 anyone?).It definitely needs to work for printf and writef.
Dec 13 2019
On Saturday, 14 December 2019 at 07:37:49 UTC, Walter Bright wrote:It definitely needs to work for printf and writef.That's an odd requirement, considering you can update writef with the compiler, and printf is legacy.
Dec 14 2019
On 12/11/2019 2:57 AM, Alexandru Ermicioi wrote:Why not just split interpolated string into just a tuple of args & strings. For example: Given: (i"I ate %apples and %bananas totalling %(apples + bananas) fruit.") Is lowered to a tuple: ("I ate ", apples, " and ", bananas," totalling ", apples + bananas," fruit.")I don't see the point of that. The user could write it that way to begin with.
Dec 13 2019
On 12/14/19 2:34 AM, Walter Bright wrote:On 12/11/2019 2:57 AM, Alexandru Ermicioi wrote:Walter, this is literally the point of string interpolation. A similar response to your entire proposal could be, why not just use writeln and write out all the items? The point is not just to put the expressions where they belong, but to be less verbose about it. The dance of quotes and commas is hard to read and hard to write. -SteveWhy not just split interpolated string into just a tuple of args & strings. For example: Given: (i"I ate %apples and %bananas totalling %(apples + bananas) fruit.") Is lowered to a tuple: ("I ate ", apples, " and ", bananas," totalling ", apples + bananas," fruit.")I don't see the point of that. The user could write it that way to begin with.
Dec 14 2019
On 12/14/2019 7:07 AM, Steven Schveighoffer wrote:On 12/14/19 2:34 AM, Walter Bright wrote:String interpolation for format strings is quite different.On 12/11/2019 2:57 AM, Alexandru Ermicioi wrote:Walter, this is literally the point of string interpolation. A similar response to your entire proposal could be, why not just use writeln and write out all the items?Why not just split interpolated string into just a tuple of args & strings. For example: Given: (i"I ate %apples and %bananas totalling %(apples + bananas) fruit.") Is lowered to a tuple: ("I ate ", apples, " and ", bananas," totalling ", apples + bananas," fruit.")I don't see the point of that. The user could write it that way to begin with.The point is not just to put the expressions where they belong, but to be less verbose about it. The dance of quotes and commas is hard to read and hard to write."I ate ", apples, " and ", bananas, " totalling ", apples + bananas, " fruit." isn't too bad. Formatting, though, won't change the issue with format strings and the disconnect between the arguments and their positions.
Dec 14 2019
On Saturday, 14 December 2019 at 21:22:41 UTC, Walter Bright wrote:On 12/14/2019 7:07 AM, Steven Schveighoffer wrote:Is format strings worth building on? With UFCS we could create types which control formatting "pi=", pi.dec(10), 255, " in hex ", 255.hexThe point is not just to put the expressions where they belong, but to be less verbose about it. The dance of quotes and commas is hard to read and hard to write."I ate ", apples, " and ", bananas, " totalling ", apples + bananas, " fruit." isn't too bad. Formatting, though, won't change the issue with format strings and the disconnect between the arguments and their positions.
Dec 14 2019
On Saturday, 14 December 2019 at 21:35:51 UTC, Tove wrote:Is format strings worth building on? With UFCS we could create types which control formatting "pi=", pi.dec(10), 255, " in hex ", 255.hexThis is already possible, though: import std; struct HexPrinter(T) { T item; void toString(scope void delegate(string) sink, FormatSpec!char fmt) const { sink(format("%x", item)); } } HexPrinter!T hex(T)(T n) { return HexPrinter!T(n); } void main() { writefln("255 = %s hex", 255.hex); } so with DIP-1027 it'd remain possible with a syntax like writefln(i"255 = $(255.hex) hex");
Dec 14 2019
On Saturday, 14 December 2019 at 07:34:05 UTC, Walter Bright wrote:On 12/11/2019 2:57 AM, Alexandru Ermicioi wrote:Yes he could. The main concern I have is that current proposal is tied to printf syntax (template string first, and then args to replace) which will be quite cumbersome for people who would like to use tuple resulting from interpolation. They will need to parse template string to find all args placeholders and then split template string on those locations in most basic case. This is unnecessary boilerplate code thrown onto user. Example above solves this issue by removing the need to parse this template string since it won't be there anymore. In any case Adam's version seems more versatile and could work nicely, allowing user to choose what he would get from interpolation. For example it could alias itself to a built version of interpolated string, and expose interface to get interpolated tuple in printf format, or in format suitable for text function. Also having such structure we could encode other information such as variable prefix syntax used in interpolation string if it is decided to have the ability to change prefix, which could be then used nicely to throw asserts on wrong interpolation syntax being used and etc. The only thing is I don't understand why a struct is not sufficient for interpolated string in Adam's proposal. Best regards, AlexandruWhy not just split interpolated string into just a tuple of args & strings. For example: Given: (i"I ate %apples and %bananas totalling %(apples + bananas) fruit.") Is lowered to a tuple: ("I ate ", apples, " and ", bananas," totalling ", apples + bananas," fruit.")I don't see the point of that. The user could write it that way to begin with.
Dec 14 2019
On Saturday, 14 December 2019 at 07:34:05 UTC, Walter Bright wrote:I don't see the point of that. The user could write it that way to begin with.Translations. Marking all your sentence fragments as translatable is messy, but there's a far worse impact on translators. They will have some trouble piecing together the sentence, then they will find it almost impossible to translate the fragments in the correct order for the data arguments. Spoken languages are not word for word equivalent.
Dec 16 2019
On Wednesday, 11 December 2019 at 09:52:21 UTC, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1027, "String Interpolation": https://github.com/dlang/DIPs/blob/148001a963f5d6e090bb6beef5caf9854372d0bc/DIPs/DIP1027.mdNice! I just have a few nitpicks: - I don't mind the required prefix 'i', but what about q{} strings? I probably want to use interpolation there as well - I know it is bikeshedding but since string interpolation is 99% syntax, I vote for "either a single $colon for variables or ${expression} for expressions", like literally every other modern language. Besides that, this is really nice.
Dec 11 2019
On Wednesday, 11 December 2019 at 11:05:25 UTC, Sebastiaan Koppe wrote:On Wednesday, 11 December 2019 at 09:52:21 UTC, Mike Parker wrote:Yes +1! It should be something common, not a dlang only syntax. => $var and ${expression} https://en.wikipedia.org/wiki/String_interpolation But this alone gives no way for formatting numbers, so maybe ${%9.6f}{fvar} ?This is the feedback thread for the first round of Community Review for DIP 1027, "String Interpolation": https://github.com/dlang/DIPs/blob/148001a963f5d6e090bb6beef5caf9854372d0bc/DIPs/DIP1027.mdNice! I just have a few nitpicks: - I don't mind the required prefix 'i', but what about q{} strings? I probably want to use interpolation there as well - I know it is bikeshedding but since string interpolation is 99% syntax, I vote for "either a single $colon for variables or ${expression} for expressions", like literally every other modern language. Besides that, this is really nice.
Dec 11 2019
On Wednesday, 11 December 2019 at 12:11:34 UTC, Martin Tschierschke wrote:Yes +1! It should be something common, not a dlang only syntax. => $var and ${expression} https://en.wikipedia.org/wiki/String_interpolation But this alone gives no way for formatting numbers, so maybe ${%9.6f}{fvar} ?My recollection is that in Python 3 that would be done {fvar: 9.6f} or something like that (not a Python programmer).
Dec 11 2019
On Wednesday, 11 December 2019 at 14:55:08 UTC, bachmeier wrote:[snip] My recollection is that in Python 3 that would be done {fvar: 9.6f} or something like that (not a Python programmer).Python's formatting is described here: https://www.python.org/dev/peps/pep-0498/#id30 so I think it would be more like {var: {9}.{6}} Scala's would be more like $val%9.6f, which I find both more concise and consistent with other D code.
Dec 11 2019
On 12/11/2019 6:55 AM, bachmeier wrote:Both these have parsing problems. The idea is to keep it parse-able with minimal grammar, which will make it easiest for people to understand.But this alone gives no way for formatting numbers, so maybe ${%9.6f}{fvar} ?My recollection is that in Python 3 that would be done {fvar: 9.6f} or something like that (not a Python programmer).
Dec 13 2019
On 12/11/2019 4:11 AM, Martin Tschierschke wrote:It should be something common, not a dlang only syntax.Unfortunately, there is enough variation in common use that there's no such thing as a common syntax.But this alone gives no way for formatting numbersYup. It's not good enough.
Dec 13 2019
On Wednesday, 11 December 2019 at 11:05:25 UTC, Sebastiaan Koppe wrote:- I know it is bikeshedding but since string interpolation is 99% syntax, I vote for "either a single $colon for variables or ${expression} for expressions", like literally every other modern language.That's definitely not bikeshedding. Given how late D is to the party on this, there's no excuse to not steal the best available syntax from other languages.
Dec 11 2019
On 12/11/2019 3:05 AM, Sebastiaan Koppe wrote:- I don't mind the required prefix 'i', but what about q{} strings? I probably want to use interpolation there as wellThe interpolation string needs to be a separate token. But I was thinking about i strings being concatenated with other strings if the others immediately follow it.- I know it is bikeshedding but since string interpolation is 99% syntax, I vote for "either a single $colon for variables or ${expression} for expressions", like literally every other modern language.Have to fit in format specifiers, too.
Dec 13 2019
On Wednesday, 11 December 2019 at 09:52:21 UTC, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1027, "String Interpolation": https://github.com/dlang/DIPs/blob/148001a963f5d6e090bb6beef5caf9854372d0bc/DIPs/DIP1027.md All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on December 25, or when I make a post declaring it complete. At the end of Round 1, if further review is deemed necessary, the DIP will be scheduled for another round of Community Review. Otherwise, it will be queued for the Final Review and Formal Assessment. Anyone intending to post feedback in this thread is expected to be familiar with the reviewer guidelines: https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md *Please stay on topic!* Thanks in advance to all who participate.Nice but it sounds a bit "hacky" to me. If i'm right this code will output "Hello %textworld123" string text = "world"; text(i"Hello %text", "123"); I hoped it was expanded to a function call rather than to a tuple... Andrea
Dec 11 2019
On Wednesday, 11 December 2019 at 11:45:07 UTC, Andrea Fontana wrote:If i'm right this code will output "Hello %textworld123"Oops, I mean "Hello %sworld123"
Dec 11 2019
On Wednesday, 11 December 2019 at 11:45:07 UTC, Andrea Fontana wrote:On Wednesday, 11 December 2019 at 09:52:21 UTC, Mike Parker wrote:If my understanding is right, string assignment is not supported by the dip, only the 2 functions writeln/printf. Which would be a quite big limitation. This would only cover 20% of my use case of string interpolation. Is my understanding correct? Kind regards AndréThis is the feedback thread for the first round of Community Review for DIP 1027, "String Interpolation": https://github.com/dlang/DIPs/blob/148001a963f5d6e090bb6beef5caf9854372d0bc/DIPs/DIP1027.md All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on December 25, or when I make a post declaring it complete. At the end of Round 1, if further review is deemed necessary, the DIP will be scheduled for another round of Community Review. Otherwise, it will be queued for the Final Review and Formal Assessment. Anyone intending to post feedback in this thread is expected to be familiar with the reviewer guidelines: https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md *Please stay on topic!* Thanks in advance to all who participate.Nice but it sounds a bit "hacky" to me. If i'm right this code will output "Hello %textworld123" string text = "world"; text(i"Hello %text", "123"); I hoped it was expanded to a function call rather than to a tuple... Andrea
Dec 11 2019
On Wednesday, 11 December 2019 at 12:31:28 UTC, Andre Pany wrote:supported by the dip, only the 2 functions writeln/printf.No, it can be passed to anything. std.string.format does it returning a string. Or you can write custom functions to read it.
Dec 11 2019
On Wednesday, 11 December 2019 at 12:31:28 UTC, Andre Pany wrote:If my understanding is right, string assignment is not supported by the dip, only the 2 functions writeln/printf. Which would be a quite big limitation. This would only cover 20% of my use case of string interpolation. Is my understanding correct? Kind regards AndréProbably we're going to add format everywhere write: string t = i"%count iterations done.".format; Andrea
Dec 11 2019
On Wednesday, 11 December 2019 at 11:45:07 UTC, Andrea Fontana wrote:I hoped it was expanded to a function call rather than to a tuple...Or maybe some kind of formatting-objects protocol? Then you could things like: f" …%1.3f{some_float}…{otherstuff}" => ( "…", string_format_f!typeof(some_float)(1,3)(some_float), "…", otherstuff ) *shrugs*
Dec 11 2019
On 12/11/2019 3:45 AM, Andrea Fontana wrote:I hoped it was expanded to a function call rather than to a tuple...Functions currently can't return tuples, meaning you couldn't make it work with printf.
Dec 13 2019
On Wednesday, 11 December 2019 at 09:52:21 UTC, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1027, "String Interpolation": https://github.com/dlang/DIPs/blob/148001a963f5d6e090bb6beef5caf9854372d0bc/DIPs/DIP1027.md writefln(i"I ate %apples and %{d}bananas")What if I don't want any space after %apples?
Dec 11 2019
On Wednesday, 11 December 2019 at 12:35:54 UTC, Rumbu wrote:i"I ate %(apples)and " just use the parenthesis version.writefln(i"I ate %apples and %{d}bananas")What if I don't want any space after %apples?
Dec 11 2019
On 12/11/2019 5:48 AM, Adam D. Ruppe wrote:just use the parenthesis version.Note that this is similar to how text macros work in the make program.
Dec 13 2019
On Wednesday, 11 December 2019 at 12:35:54 UTC, Rumbu wrote:On Wednesday, 11 December 2019 at 09:52:21 UTC, Mike Parker wrote:Then you write %(apples)nospace.This is the feedback thread for the first round of Community Review for DIP 1027, "String Interpolation": https://github.com/dlang/DIPs/blob/148001a963f5d6e090bb6beef5caf9854372d0bc/DIPs/DIP1027.md writefln(i"I ate %apples and %{d}bananas")What if I don't want any space after %apples?
Dec 11 2019
On Wednesday, 11 December 2019 at 09:52:21 UTC, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1027, "String Interpolation": https://github.com/dlang/DIPs/blob/148001a963f5d6e090bb6beef5caf9854372d0bc/DIPs/DIP1027.md All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on December 25, or when I make a post declaring it complete. At the end of Round 1, if further review is deemed necessary, the DIP will be scheduled for another round of Community Review. Otherwise, it will be queued for the Final Review and Formal Assessment. Anyone intending to post feedback in this thread is expected to be familiar with the reviewer guidelines: https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md *Please stay on topic!* Thanks in advance to all who participate.From the dip it seems that it is only valid for writefln & co So a code like: auto myText = i"I ate% apples" would not be valid. Correct me if I'm wrong but from my point of view this "String interpolation" is completely useless. I wish D had a string interpolation like Kotlin
Dec 11 2019
On Wednesday, 11 December 2019 at 12:50:34 UTC, Ernesto Castellotti wrote:e if I'm wrong but from my point of view this "String interpolation" is completely useless. I wish D had a string interpolation like KotlinThe problem is making it work with something like a string-appender. If you don't have GC then you might want to estimate buffer size before allocating, so you need 2 passes. * pass 1: run over all items and caculate length *allocate buffer * pass 2: call formatting-objects on each item and ask them to write themselves to a slice. But a metaprogramming oriented language really should to support custom formatters well in interpolated strings.
Dec 11 2019
On Wednesday, 11 December 2019 at 12:50:34 UTC, Ernesto Castellotti wrote:On Wednesday, 11 December 2019 at 09:52:21 UTC, Mike Parker wrote:this code should be valid although it wont be a string but a tuple of string & args ready for printing by stdio family of printer functions. Current implementation also requires that a function call to be used to get a string, which defies the entire purpose of interpolated strings. It either should be a simple tuple as suggested above (then i could live with additional func call to get resulting string), or return an interpolated string ready to be used (no additional function call). Best regards, Alexandru.This is the feedback thread for the first round of Community Review for DIP 1027, "String Interpolation": https://github.com/dlang/DIPs/blob/148001a963f5d6e090bb6beef5caf9854372d0bc/DIPs/DIP1027.md All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on December 25, or when I make a post declaring it complete. At the end of Round 1, if further review is deemed necessary, the DIP will be scheduled for another round of Community Review. Otherwise, it will be queued for the Final Review and Formal Assessment. Anyone intending to post feedback in this thread is expected to be familiar with the reviewer guidelines: https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md *Please stay on topic!* Thanks in advance to all who participate.From the dip it seems that it is only valid for writefln & co So a code like: auto myText = i"I ate% apples" would not be valid. Correct me if I'm wrong but from my point of view this "String interpolation" is completely useless. I wish D had a string interpolation like Kotlin
Dec 11 2019
On Wednesday, 11 December 2019 at 12:50:34 UTC, Ernesto Castellotti wrote:On Wednesday, 11 December 2019 at 09:52:21 UTC, Mike Parker wrote:It is allowed everywhere where a tuple expression is allowed auto myText = "I ate%s", apples doesn't make sense[...]From the dip it seems that it is only valid for writefln & co So a code like: auto myText = i"I ate% apples" would not be valid.Correct me if I'm wrong but from my point of view this "String interpolation" is completely useless. I wish D had a string interpolation like Kotlin
Dec 11 2019
On Wednesday, 11 December 2019 at 15:55:35 UTC, Patrick Schluter wrote:On Wednesday, 11 December 2019 at 12:50:34 UTC, Ernesto Castellotti wrote:It works already (un?)fortunately: auto test = AliasSeq!("The product of %s and %s is %s", 2, 5, 10); writeln(test); //Prints "The product of %s and %s is %s2510" writefln(test); //Print "The product of 2 and 5 is 10" This DIP is just taking that 1 extra small step to allow i"" strings to be lowered to tuple literals.On Wednesday, 11 December 2019 at 09:52:21 UTC, Mike Parker wrote:It is allowed everywhere where a tuple expression is allowed auto myText = "I ate%s", apples doesn't make sense[...]From the dip it seems that it is only valid for writefln & co So a code like: auto myText = i"I ate% apples" would not be valid.
Dec 11 2019
On Wednesday, 11 December 2019 at 17:49:45 UTC, Meta wrote:On Wednesday, 11 December 2019 at 15:55:35 UTC, Patrick Schluter wrote:Yes this is the purpose of the dip, but it is not what I expect for the string interpolation. This would require explicitly calling the functions of a library to convert the tuple into a string, I would like it to be done literals implicitly.On Wednesday, 11 December 2019 at 12:50:34 UTC, Ernesto Castellotti wrote:It works already (un?)fortunately: auto test = AliasSeq!("The product of %s and %s is %s", 2, 5, 10); writeln(test); //Prints "The product of %s and %s is %s2510" writefln(test); //Print "The product of 2 and 5 is 10" This DIP is just taking that 1 extra small step to allow i"" strings to be lowered to tuple literals.On Wednesday, 11 December 2019 at 09:52:21 UTC, Mike Parker wrote:It is allowed everywhere where a tuple expression is allowed auto myText = "I ate%s", apples doesn't make sense[...]From the dip it seems that it is only valid for writefln & co So a code like: auto myText = i"I ate% apples" would not be valid.
Dec 11 2019
On 12/11/2019 9:49 AM, Meta wrote:This DIP is just taking that 1 extra small step to allow i"" strings to be lowered to tuple literals.You're right. That's really all it does. It will work anywhere a tuple will work.
Dec 13 2019
On Wednesday, 11 December 2019 at 09:52:21 UTC, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1027, "String Interpolation": https://github.com/dlang/DIPs/blob/148001a963f5d6e090bb6beef5caf9854372d0bc/DIPs/DIP1027.mdWhat happens in a template? --- string str = "work"; template myTemplate(string str, Args...) {} myTemplate!(i"will this %str as expected?"); --- How will the params be passed? Aliased?
Dec 11 2019
On 12/11/2019 5:00 AM, Sebastiaan Koppe wrote:--- string str = "work"; template myTemplate(string str, Args...) {} myTemplate!(i"will this %str as expected?"); --- How will the params be passed? Aliased?As if you wrote: myTemplate!("will this %s as expected", str);
Dec 13 2019
On Wednesday, 11 December 2019 at 09:52:21 UTC, Mike Parker wrote: The transformation is WRONG! '%%', a '%' is written to the output string. it must be '%%', a '%%' is written to the output string or else you will have problems Example. If I have following expression writefln(i"I ate %{d}apples and %{d}bananas totalling %{d}(100*apples/bananas) %%fruit\n"); it would be lowered to writefln("I ate %d and %d totalling %d %fruit\n", apples, bananas, (100*apples/bananas)); The %% being transformed to a simple %, we now have a %f with no parameter => compilation error or worse undefined behaviour in case of printf. I would have to write writefln(i"I ate %{d}apples and %{d}bananas totalling %{d}(100*apples/bananas) %%%%fruit\n"); which is not good. So '%%' have to be untouched by the lowering
Dec 11 2019
On 12/11/2019 7:37 AM, Patrick Schluter wrote:The transformation is WRONG!You're quite right. I missed that. With some noodling about with this problem, I've decided to replace the % with $. Then, % just becomes an ordinary character. Using $ also has the advantage of visually distinguishing a % format string from an interpolated format string.
Dec 14 2019
On Saturday, 14 December 2019 at 08:00:41 UTC, Walter Bright wrote:I've decided to replace the % with $. Then, % just becomes an ordinary character. Using $ also has the advantage of visually distinguishing a % format string from an interpolated format string.Nice. It’s also more like what several other languages do. Bastiaan.
Dec 14 2019
On Wednesday, 11 December 2019 at 09:52:21 UTC, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1027, "String Interpolation": https://github.com/dlang/DIPs/blob/148001a963f5d6e090bb6beef5caf9854372d0bc/DIPs/DIP1027.md [...]This is amazing and I would use it straight away. To preempt any suggestion to just use format with %n$s positional specifiers instead, I present to you non-trivial cases of Bash colour highlighting. enum logtint = "\033[1;32m"; enum warningtint = "\033[1;31m"; enum resettint = "\033[0m"; writefln("%3$sException: %1$s%2$s%3$s (at %1$s%4$s%3$s:%1$s%5$d%3$s)%6$s", logtint, e.msg, warningtint, e.file, e.line, resettint);
Dec 11 2019
On 12/11/2019 10:40 AM, Anonymouse wrote:To preempt any suggestion to just use format with %n$s positional specifiers instead, I present to you non-trivial cases of Bash colour highlighting. enum logtint = "\033[1;32m"; enum warningtint = "\033[1;31m"; enum resettint = "\033[0m"; writefln("%3$sException: %1$s%2$s%3$s (at %1$s%4$s%3$s:%1$s%5$d%3$s)%6$s", logtint, e.msg, warningtint, e.file, e.line, resettint);Not going to use positional specifiers: 1. I don't see much point to them 2. more complexity 3. problems with evaluating an argument multiple times when there are side effects.
Dec 14 2019
I'm not really sure if the balance of added complexity vs. payoff is in favor of payoff. They only time I felt the need for such a feature was when I had very long DelimitedStrings. And those long strings where a constant source bugs, so I split them up and the field need for interpolated strings want away with the bugs. Not being able to use * will stop me using this feature in many places. The rationale about "missing arguments, wrong format specifier,... " Is a mute point IMO. format!"%d"(13.37) does the same thing already without any language change. I thought the idea was not to introduce language changes if a library solution can do most of it already. I find that the readability argument is highly subjective. The first part of the rationale is, IHO, already pointing to the solution. Short strings are easy to manage. So let's promote short strings in combination with format!"%s" and output ranges. How will this feature work at CT. Format doesn't even work completely at CT. I know this goes a bit off topic, but IMO this is a feature that is wanted, because other languages have it. And we want to say we have it too. I think it's a lot nicer to say, we don't need this, because our templates can already do that. TL/DR: not a fan
Dec 11 2019
On Wednesday, 11 December 2019 at 18:58:46 UTC, Robert Schadek wrote:I'm not really sure if the balance of added complexity vs. payoff is in favor of payoff. They only time I felt the need for such a feature was when I had very long DelimitedStrings. And those long strings where a constant source bugs, so I split them up and the field need for interpolated strings want away with the bugs. Not being able to use * will stop me using this feature in many places. The rationale about "missing arguments, wrong format specifier,... " Is a mute point IMO. format!"%d"(13.37) does the same thing already without any language change. I thought the idea was not to introduce language changes if a library solution can do most of it already. I find that the readability argument is highly subjective. The first part of the rationale is, IHO, already pointing to the solution. Short strings are easy to manage. So let's promote short strings in combination with format!"%s" and output ranges. How will this feature work at CT. Format doesn't even work completely at CT. I know this goes a bit off topic, but IMO this is a feature that is wanted, because other languages have it. And we want to say we have it too. I think it's a lot nicer to say, we don't need this, because our templates can already do that. TL/DR: not a fanIt can *almost* already be done with templates: https://github.com/Abscissa/scriptlike#string-interpolation The main sticking point is that you have to write mixin(interp!"....") so the symbols will be looked up in the proper scope. Unfortunately, that also means that the above syntax is the best a library solution can do, currently.
Dec 11 2019
On Wednesday, 11 December 2019 at 19:15:18 UTC, Meta wrote:The main sticking point is that you have to write mixin(interp!"....") so the symbols will be looked up in the proper scope. Unfortunately, that also means that the above syntax is the best a library solution can do, currently.Maybe "mixin" could be a return type requiring CTFE and re-evaluated in the calling context? A bit dangerous perhaps.
Dec 11 2019
On Wednesday, 11 December 2019 at 20:28:21 UTC, Ola Fosheim Grøstad wrote:On Wednesday, 11 December 2019 at 19:15:18 UTC, Meta wrote:Yeah, I think if it comes down to adding a new language feature to the compiler, or changing how mixins behave in such a way that may be cause for security concerns, it's less costly to add the language feature. Really, though, all that's needed is to allow mixin templates to be mixed in without using the `mixin` keyword (I say "all", but that's quite a large language change): string interp(string s)() { .... } mixin template i(string s) { enum i = mixin(interp!s); } auto n = 2, m = 5; auto s = i!"The product of ${n} and ${m} is ${n * m}"; writefln(s);The main sticking point is that you have to write mixin(interp!"....") so the symbols will be looked up in the proper scope. Unfortunately, that also means that the above syntax is the best a library solution can do, currently.Maybe "mixin" could be a return type requiring CTFE and re-evaluated in the calling context? A bit dangerous perhaps.
Dec 11 2019
On Wednesday, 11 December 2019 at 20:46:03 UTC, Meta wrote:Really, though, all that's needed is to allow mixin templates to be mixed in without using the `mixin` keyword (I say "all", but that's quite a large language change):Could one option be to use another symbol than «!» and make it imply the mixin? … f = some_formatter_that_builds_a_string …; immutable s = f!!"My name is {this.name}";
Dec 11 2019
On Wednesday, 11 December 2019 at 20:57:35 UTC, Ola Fosheim Grøstad wrote:On Wednesday, 11 December 2019 at 20:46:03 UTC, Meta wrote:I like this. A universal improvement that also happens to enable all kinds of string interpolation, including SQL. Bastiaan.Really, though, all that's needed is to allow mixin templates to be mixed in without using the `mixin` keyword (I say "all", but that's quite a large language change):Could one option be to use another symbol than «!» and make it imply the mixin? … f = some_formatter_that_builds_a_string …; immutable s = f!!"My name is {this.name}";
Dec 11 2019
On Wednesday, 11 December 2019 at 23:17:37 UTC, Bastiaan Veelo wrote:On Wednesday, 11 December 2019 at 20:57:35 UTC, Ola Fosheim Grøstad wrote:Another option is to add unicode support: fmt«I am {name}!» ==> mixin(fmt!"I am {name}!") (on my mac I get those symbols by hitting alt-shift-v and alt-shift-b)immutable s = f!!"My name is {this.name}";I like this. A universal improvement that also happens to enable all kinds of string interpolation, including SQL.
Dec 11 2019
On Wednesday, 11 December 2019 at 20:46:03 UTC, Meta wrote:On Wednesday, 11 December 2019 at 20:28:21 UTC, Ola Fosheim Grøstad wrote:This would be really cool[...]Yeah, I think if it comes down to adding a new language feature to the compiler, or changing how mixins behave in such a way that may be cause for security concerns, it's less costly to add the language feature. Really, though, all that's needed is to allow mixin templates to be mixed in without using the `mixin` keyword (I say "all", but that's quite a large language change): string interp(string s)() { .... } mixin template i(string s) { enum i = mixin(interp!s); } auto n = 2, m = 5; auto s = i!"The product of ${n} and ${m} is ${n * m}"; writefln(s);
Dec 11 2019
On Thursday, 12 December 2019 at 06:47:28 UTC, Ernesto Castellotti wrote:On Wednesday, 11 December 2019 at 20:46:03 UTC, Meta wrote:One idea I've seen floated in a previous thread is to introduce a new unary operator that could take the place of the "mixin" keyword. So instead of auto s = mixin(interp!"My ${vehicle} is full of ${creature}s!"); you could instead write something like this: auto s = interp!"My ${vehicle} is full of ${creature}s!";Really, though, all that's needed is to allow mixin templates to be mixed in without using the `mixin` keyword (I say "all", but that's quite a large language change): string interp(string s)() { .... } mixin template i(string s) { enum i = mixin(interp!s); } auto n = 2, m = 5; auto s = i!"The product of ${n} and ${m} is ${n * m}"; writefln(s);This would be really cool
Dec 11 2019
On 12/11/2019 10:47 PM, Ernesto Castellotti wrote:This would be really coolI tried that (the enum in template trick). It's close, but still no banana.
Dec 14 2019
On Wednesday, 11 December 2019 at 18:58:46 UTC, Robert Schadek wrote:I'm not really sure if the balance of added complexity vs. payoff is in favor of payoff.Disagree. This proposition strikes exactly the right balance would agree with you. This proposition though is just a simple composition of the existing C heritage and the availaible D feature (tuple).They only time I felt the need for such a feature was when I had very long DelimitedStrings. And those long strings where a constant source bugs, so I split them up and the field need for interpolated strings want away with the bugs.So you complexified your code because of a restriction of the language.Not being able to use * will stop me using this feature in many places. The rationale about "missing arguments, wrong format specifier,... " Is a mute point IMO. format!"%d"(13.37) doesMOOT not mutethe same thing already without any language change. I thought the idea was not to introduce language changes if a library solution can do most of it already. I find that the readability argument is highly subjective.It is but it is also true that from more than 4 parameters in a format string it gets more and more noisy.The first part of the rationale is, IHO, already pointing to the solution. Short strings are easy to manage. So let's promote short strings in combination with format!"%s" and output ranges. How will this feature work at CT. Format doesn't even work completely at CT.It's a problem with format and is perpendicular to this DIP, i.e. if this DIP is adopted or not, it will not change anything to the issues of format.I know this goes a bit off topic, but IMO this is a feature that is wanted, because other languages have it. And we want to say we have it too.May be sometimes it is good to look why certain features are spreading like wildfire. C format specifiers were a regression compared to what was available at that time (in Pascal or even Cobol), but as C had so much other things to it, people tended to accept the strange and ugly printf formatting, but it's clear that i was universally loathed. That's why C++ tried this worse shift syntax and other languages tried other solutions. It is not because we in the end managed to get used to the outdated and dangerous printf format that it is good in the first place. This DIP is simple enough that it is a good candidate imho to be tried.I think it's a lot nicer to say, we don't need this, because our templates can already do that.
Dec 11 2019
On Wednesday, 11 December 2019 at 19:34:01 UTC, Patrick Schluter wrote:Cobol), but as C had so much other things to it, people tended to accept the strange and ugly printf formatting, but it's clear that i was universally loathed. That's why C++ tried this worse shift syntax and other languages tried other solutions. It is not because we in the end managed to get used to the outdated and dangerous printf format that it is good in the first place. This DIP is simple enough that it is a good candidate imho to be tried.If something is bad… (…and I agree, printf is not good.) Why would you embrace it by making it part of the language? Currently it only part of a library and can be phased out. Make it part of the language and you'll be stuck with it. Creating a better solution and create a wrapper for printf and other C-APIs would be the better approach. Otherwise you'll end up with another interpolated string version... down the road. How many string-literals can a language handle?
Dec 11 2019
On Wednesday, 11 December 2019 at 19:34:01 UTC, Patrick Schluter wrote:So you complexified your code because of a restriction of the language.Not at all, before I was trying to do to much. With multiple format calls, I made the code boring and easy to follow.True, so you would split up the code, right!? If both format styles don't work with more than x arguments, why do I need to styles to not get the work done. One is enough to shoot myself in the foot, isn't it.Not being able to use * will stop me using this feature in many places. The rationale about "missing arguments, wrong format specifier,... " Is a mute point IMO. format!"%d"(13.37) doesMOOT not mutethe same thing already without any language change. I thought the idea was not to introduce language changes if a library solution can do most of it already. I find that the readability argument is highly subjective.It is but it is also true that from more than 4 parameters in a format string it gets more and more noisy.Why do we need it then?The first part of the rationale is, IHO, already pointing to the solution. Short strings are easy to manage. So let's promote short strings in combination with format!"%s" and output ranges. How will this feature work at CT. Format doesn't even work completely at CT.It's a problem with format and is perpendicular to this DIP, i.e. if this DIP is adopted or not, it will not change anything to the issues of format.format!""() is not dangerous, if it is please show me why, I use it all over the place. I'm also not sure why it is outdated, format is very flexible and powerful, i.e. array formatting is just awesome.I know this goes a bit off topic, but IMO this is a feature that is wanted, because other languages have it. And we want to say we have it too.May be sometimes it is good to look why certain features are spreading like wildfire. C format specifiers were a regression compared to what was available at that time (in Pascal or even Cobol), but as C had so much other things to it, people tended to accept the strange and ugly printf formatting, but it's clear that i was universally loathed. That's why C++ tried this worse shift syntax and other languages tried other solutions. It is not because we in the end managed to get used to the outdated and dangerous printf format that it is good in the first place. This DIP is simple enough that it is a good candidate imho to be tried.
Dec 11 2019
On 12/11/2019 10:58 AM, Robert Schadek wrote:Not being able to use * will stop me using this feature in many places.That's right. I have a fix for that!I thought the idea was not to introduce language changes if a library solution can do most of it already.I tried. It just doesn't get us there without some awkward syntax.TL/DR: not a fanA reasonable point of view. D works fine without interpolated strings. This also motivated the design to stick to something as simple as possible - just a dash of syntactic sugar.
Dec 14 2019
On Wed, Dec 11, 2019 at 09:52:21AM +0000, Mike Parker via Digitalmars-d wrote:This is the feedback thread for the first round of Community Review for DIP 1027, "String Interpolation": https://github.com/dlang/DIPs/blob/148001a963f5d6e090bb6beef5caf9854372d0bc/DIPs/DIP1027.md[...] 1) The way this DIP is worded belies its true power, which I suspect some people are unaware of. Part of this is because the writefln/printf example chosen for the Description section makes it appear as though this DIP is only about writefln or printf formatting. It would be nice(r) if the DIP included a section describing use cases outside of writefln. For example: readable yet type-safe database query formatting: by writing a format string parser that turns '%x' into '?' and generates SQL bind commands for the corresponding arguments: string table = "mytable"; string key = "key-that!needs'escap1ng"; double value = 3.14159; int index = 12345; DateTime lastTime = getCurDate(); database.exec(i"UPDATE %table SET key=%key, value=%{f}value WHERE index < %{d}index AND timestamp > %{D}lastTime"); (Note that '%D' is not a writefln-supported format, presumably it's something database.exec() understands.) 2) The previous example does bring up another issue: is there a nice way to handle long interpolated strings, i.e., wrap long interpolated strings to multiple lines? I.e., does the following work? database.exec(i"UPDATE %table SET key=%key, value=%{f}value "~ "WHERE index < %{d}index AND "~ "timestamp > %{D}lastTime"); If not, is there an alternative? One of the key arguments of the DIP is that traditional format strings become unwieldy when the length increases and the number of arguments increases. But how does the proposed interpolated string syntax mitigate the very same problems in its own syntax? 3) Someone has already pointed out the problem of interpreting %% as %, because: double grade = 89.5; writefln(i"Your grade is %{.2f}grade%%."); gets turned into: double grade = 89.5; writefln("Your grade is %.2f%.", grade); Note the dangling % at the end, which will writefln to throw an error. Under the current syntax, you'd have to write "%%%%" to get a single '%' in the writefln output, which seems excessive. Counterproposal: %% should be copied literally as %% in the output. T -- PNP = Plug 'N' Pray
Dec 11 2019
On 12/11/2019 11:33 AM, H. S. Teoh wrote:2) The previous example does bring up another issue: is there a nice way to handle long interpolated strings, i.e., wrap long interpolated strings to multiple lines? I.e., does the following work? database.exec(i"UPDATE %table SET key=%key, value=%{f}value "~ "WHERE index < %{d}index AND "~ "timestamp > %{D}lastTime");No. The trouble happens with how semantic analysis is done - leaves first, then non-leaves. It's just the wrong order to make the concatenation make sense. I've thought about this for the last week. The most practical idea is to simply concatenate adjacent strings, as in: database.exec(i"UPDATE %table SET key=%key, value=%{f}value " "WHERE index < %{d}index AND " "timestamp > %{D}lastTime"); I.e. the 'i' string comes first, and gets concatenated with any following string literals. This also enables using 'q' strings as interpolated strings: i"" q{a + b}
Dec 14 2019
On 2019-12-14 09:36, Walter Bright wrote:I've thought about this for the last week. The most practical idea is to simply concatenate adjacent strings, as in: database.exec(i"UPDATE %table SET key=%key, value=%{f}value " "WHERE index < %{d}index AND " "timestamp > %{D}lastTime"); I.e. the 'i' string comes first, and gets concatenated with any following string literals. This also enables using 'q' strings as interpolated strings: i"" q{a + b}Implicit string concatenation is deprecated and gives an error. -- /Jacob Carlborg
Dec 14 2019
On 12/14/2019 5:34 AM, Jacob Carlborg wrote:Implicit string concatenation is deprecated and gives an error.I know. But i strings aren't string literals, and this would be special cased for that. And I wouldn't have proposed that if ~ would work, but it does not work for this.
Dec 14 2019
On 12/14/19 3:36 AM, Walter Bright wrote:On 12/11/2019 11:33 AM, H. S. Teoh wrote:What if the strings are all interpolated strings? e.g.: database.exec(i"UPDATE %table SET key=$key, value=${f}value "~ i"WHERE index < ${d}index AND "~ i"timestamp > ${D}lastTime"); I don't know enough about the grammar/implementation to know if this makes more sense or not.2) The previous example does bring up another issue: is there a nice way to handle long interpolated strings, i.e., wrap long interpolated strings to multiple lines? I.e., does the following work? database.exec(i"UPDATE %table SET key=%key, value=%{f}value "~ "WHERE index < %{d}index AND "~ "timestamp > %{D}lastTime");No. The trouble happens with how semantic analysis is done - leaves first, then non-leaves. It's just the wrong order to make the concatenation make sense.I've thought about this for the last week. The most practical idea is to simply concatenate adjacent strings, as in: database.exec(i"UPDATE %table SET key=%key, value=%{f}value " "WHERE index < %{d}index AND " "timestamp > %{D}lastTime");But we deprecated that because it's too error prone.I.e. the 'i' string comes first, and gets concatenated with any following string literals. This also enables using 'q' strings as interpolated strings: i"" q{a + b}I actually think 'i' should be able to go before any string literal. e.g.: iq{$a + $b} i`$a + $b` Just like suffixes can be applied to any string literal to alter the width. -Steve
Dec 14 2019
On 12/14/2019 6:47 AM, Steven Schveighoffer wrote:What if the strings are all interpolated strings? e.g.: database.exec(i"UPDATE %table SET key=$key, value=${f}value "~ i"WHERE index < ${d}index AND "~ i"timestamp > ${D}lastTime");Then you'll get a tuple that looks like: "UPDATE %s SET key=%s, value=%f ", key, value, "WHERE index < %d AND ", index, "timestamp > %D", lastTime which won't work for printf or writefln.I actually think 'i' should be able to go before any string literal. e.g.: iq{$a + $b} i`$a + $b`Since the other method works, I am striving to keep things as simple as possible. There needs to be very good reasons for gratuitous multiple ways of doing something, and I don't see one here. Of course, then there's "what about qi strings", aaggghhhh.
Dec 14 2019
On 12/14/19 8:21 PM, Walter Bright wrote:On 12/14/2019 6:47 AM, Steven Schveighoffer wrote:Why? I mean concatenation of Tuples isn't defined to do anything. pragma(msg, AliasSeq!("hello", "there") ~ AliasSeq!("world", "and everyone else")); Error: incompatible types for (tuple("hello", "there")) ~ (tuple("world", "and everyone else")): both operands are of type (string, string) But we could define it for interpolated string tuples to be the concatenation of the format strings followed by the AliasSeq of all the fields in order. This is the time to make these decisions, because it will be hard to add later. Removing automatic string concatenation was a great addition, but took a long time to get into the language, due to not breaking existing code. I'd hate to have to do it again.What if the strings are all interpolated strings? e.g.: database.exec(i"UPDATE %table SET key=$key, value=${f}value "~ i"WHERE index < ${d}index AND "~ i"timestamp > ${D}lastTime");Then you'll get a tuple that looks like: "UPDATE %s SET key=%s, value=%f ", key, value, "WHERE index < %d AND ", index, "timestamp > %D", lastTimeI'm proposing you DON'T make the other method work (it doesn't now). There doesn't need to be multiple ways to do string literals. And in fact, concatenation of interpolated string literals (as proposed above) would work well to provide the most expressive power, as you could concatenate any style of interpolated literals together, just like you can for uninterpolated literals. And it's not complicated. The postfix characters of `c`, `w`, and `d` do not warrant complicated explanations in the spec, and are usable on any of the string literal types. An `i` prefix is similar. All that is needed is to say "if you put `i` in front of a string literal (any string literal) it becomes an interpolated string literal"I actually think 'i' should be able to go before any string literal. e.g.: iq{$a + $b} i`$a + $b`Since the other method works, I am striving to keep things as simple as possible. There needs to be very good reasons for gratuitous multiple ways of doing something, and I don't see one here.Of course, then there's "what about qi strings", aaggghhhh.That's not grammatically correct. It would be rejected. The "interpolated" property is orthogonal to the string literal method, and must come before it. -Steve
Dec 16 2019
On 12/16/2019 9:31 AM, Steven Schveighoffer wrote:Why? I mean concatenation of Tuples isn't defined to do anything.I did concatenate the tuples in the most obvious manner - concatenating them. It produces an unusable result.But we could define it for interpolated string tuples to be the concatenation of the format strings followed by the AliasSeq of all the fields in order.Yes, we could, and then tuple concatenation would be useless for any other use of tuple concatenation.This is the time to make these decisions, because it will be hard to add later. Removing automatic string concatenation was a great addition, but took a long time to get into the language, due to not breaking existing code. I'd hate to have to do it again.There isn't a better way - and it won't be string concatenation. It'll be interpolated string concatenation, as interpolated strings are not strings at all.It works in the PR I've submitted for this DIP.Since the other method works, I am striving to keep things as simple as possible. There needs to be very good reasons for gratuitous multiple ways of doing something, and I don't see one here.I'm proposing you DON'T make the other method work (it doesn't now).And it's not complicated.I know supporting iq tokens is not complicated. It's just unnecessary. We can always add it later as necessary without breaking things.D supports u, Lu, uL, U, UL, LU integer literals because I was stupid. At least `l` is not allowed.Of course, then there's "what about qi strings", aaggghhhh.That's not grammatically correct. It would be rejected. The "interpolated" property is orthogonal to the string literal method, and must come before it.
Dec 17 2019
On Tuesday, 17 December 2019 at 09:13:52 UTC, Walter Bright wrote:On 12/16/2019 9:31 AM, Steven Schveighoffer wrote: I know supporting iq tokens is not complicated. It's just unnecessary. We can always add it later as necessary without breaking things.Well they would be a tremendous addition for metaprogramming facilities that are using mixins, since they will increase by a lot mixin code readability. Best regards, Alexandru.
Dec 17 2019
On Saturday, 14 December 2019 at 08:36:15 UTC, Walter Bright wrote:On 12/11/2019 11:33 AM, H. S. Teoh wrote:One thing to note is that if string interpolation returns a struct like Adam proposed, concatenation would be possible between interpolated strings.2) The previous example does bring up another issue: is there a nice way to handle long interpolated strings, i.e., wrap long interpolated strings to multiple lines? I.e., does the following work? database.exec(i"UPDATE %table SET key=%key, value=%{f}value "~ "WHERE index < %{d}index AND "~ "timestamp > %{D}lastTime");No. The trouble happens with how semantic analysis is done - leaves first, then non-leaves. It's just the wrong order to make the concatenation make sense. I've thought about this for the last week. The most practical idea is to simply concatenate adjacent strings, as in: database.exec(i"UPDATE %table SET key=%key, value=%{f}value " "WHERE index < %{d}index AND " "timestamp > %{D}lastTime"); I.e. the 'i' string comes first, and gets concatenated with any following string literals. This also enables using 'q' strings as interpolated strings: i"" q{a + b}
Dec 14 2019
On 12/11/19 4:52 AM, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1027, "String Interpolation": https://github.com/dlang/DIPs/blob/148001a963f5d6e090bb6beef5caf9854372 0bc/DIPs/DIP1027.md All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on December 25, or when I make a post declaring it complete. At the end of Round 1, if further review is deemed necessary, the DIP will be scheduled for another round of Community Review. Otherwise, it will be queued for the Final Review and Formal Assessment. Anyone intending to post feedback in this thread is expected to be familiar with the reviewer guidelines: https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md *Please stay on topic!* Thanks in advance to all who participate.First, I like the concept. It fixes the issue of "which parameters are string literals and which are variables?" issue of the straight lower-to-tuple design. But there are a couple problems. This is very much focused on writef and printf. What about other functions that accept similar string + arg tuple, but don't use %s specifiers? Perfect example is SQL: query("select * from sometable where date < ?", someDate); With the interpolation string: query(i"select * from sometable where date < %someDate"); This translates to: query("select * from sometable where date < %s", someDate); which is not correct SQL syntax. This means I have to create a separate function that accepts interpolated strings (can't be the same name because it would be the same parameters for overloading!) and inside that function, I need to TRANSLATE the formatted string into something sql can understand. Not only that, but I have to do it at runtime, since query accepts a string as a runtime parameter. Not only that, but this doesn't provide a mechanism to hook compile-time format strings at all, even though the format string is known at compile-time. The other problem is that you are using % for the interpolated fields. This is quite puzzling, considering that the main target (printf and writef) uses % as the format specifier. Why not just change the specifier to $ or {} or \() or \{} or literally any of the other interpolation systems out there. Then you don't need the %%%% mentioned elsewhere to make one percentage sign. If we can think of a way to hook the string generation and have the parameters come afterwards, that would be ideal. For example, if you lowered (and I'm going to use a better format specifier here): i"I ate \({d}apples) and \(bananas) totaling \(apples + bananas) fruit." to InterpStr!("I ate ", FormatSpec!("d"), " and ", FormatSpec!(""), " totaling ", FormatSpec!(""), " fruit."), apples, bananas, apples + bananas Where InterpStr and FormatSpec were defined by the library to be whatever Druntime specified, then you could handle any cases, and provide the most . For example, writef could accept the type as the first parameter, and translate easily into a standard writef call, or avoid having to parse the format specifiers all together! This wouldn't work with printf. But I'm not so sure that's a huge problem. One could easily wrap printf in something D-ish. Again, like the concept, but it's too narrowly focused on printf and writef. -Steve
Dec 11 2019
On Wednesday, 11 December 2019 at 20:38:49 UTC, Steven Schveighoffer wrote:This is very much focused on writef and printf. What about other functions that accept similar string + arg tuple, but don't use %s specifiers? Perfect example is SQL: query("select * from sometable where date < ?", someDate); With the interpolation string: query(i"select * from sometable where date < %someDate"); This translates to: query("select * from sometable where date < %s", someDate);query(i"select * from sometable where date < %someDate".format);
Dec 11 2019
On 12/11/19 3:59 PM, Andrea Fontana wrote:On Wednesday, 11 December 2019 at 20:38:49 UTC, Steven Schveighoffer wrote:https://en.wikipedia.org/wiki/SQL_injection Besides, this is bad for performance, you are translating a type to a string, just to send it to the server, to have it translate it back into the type. Sending the type directly is much more efficient. What I want is what I first typed, just in a nicer format. D has such great power at translating code, it should be able to do this. I don't see why we would settle for something that basically is a "nicer" writef or format when it could be used everywhere. -SteveThis is very much focused on writef and printf. What about other functions that accept similar string + arg tuple, but don't use %s specifiers? Perfect example is SQL: query("select * from sometable where date < ?", someDate); With the interpolation string: query(i"select * from sometable where date < %someDate"); This translates to: query("select * from sometable where date < %s", someDate);query(i"select * from sometable where date < %someDate".format);
Dec 11 2019
On Wed, Dec 11, 2019 at 03:38:49PM -0500, Steven Schveighoffer via Digitalmars-d wrote: [...]But there are a couple problems. This is very much focused on writef and printf. What about other functions that accept similar string + arg tuple, but don't use %s specifiers? Perfect example is SQL: query("select * from sometable where date < ?", someDate); With the interpolation string: query(i"select * from sometable where date < %someDate"); This translates to: query("select * from sometable where date < %s", someDate); which is not correct SQL syntax.[...] Here's a potential 2-step fix: 1) Change the interpretation of `%({X}varname)` to mean "use `X` instead of %s as placeholder in output string", rather than "use `%X` ...". I.e.: i"%abc" == tuple("%s", abc); i"%({%x}abc)" == tuple("%x", abc); i"%({?}abc)" == tuple("?", abc); // bingo, SQL syntax! 2) Then, in light of the %%%% problem, and to fix the repeated % in "%{%x}abc", change the default metacharacter to something like $: i"$abc" == tuple("%s", abc); i"$({%d}abc)" == tuple("%d", abc); i"$({?}abc)" == tuple("?", abc); For convenient interop with printf/writefln, we can still default to "%s" as the default placeholder, but the {} syntax now no longer assumes printf syntax, making i"" literals MUCH more useful in many more places outside the purvey of printf/writefln. So you'd do SQL strings like this: string name; int serial; float cost; db.exec(i"INSERT INTO mytable VALUES (${?}name, ${?}serial, ${?}cost)"); which translates the last line to: db.exec("INSERT INTO mytable VALUES (?, ?, ?)", name, serial, cost); without the need for any intermediate format string parser. T -- VI = Visual Irritation
Dec 11 2019
On 12/11/19 5:37 PM, H. S. Teoh wrote:Here's a potential 2-step fix: 1) Change the interpretation of `%({X}varname)` to mean "use `X` instead of %s as placeholder in output string", rather than "use `%X` ...". I.e.: i"%abc" == tuple("%s", abc); i"%({%x}abc)" == tuple("%x", abc); i"%({?}abc)" == tuple("?", abc); // bingo, SQL syntax! 2) Then, in light of the %%%% problem, and to fix the repeated % in "%{%x}abc", change the default metacharacter to something like $: i"$abc" == tuple("%s", abc); i"$({%d}abc)" == tuple("%d", abc); i"$({?}abc)" == tuple("?", abc); For convenient interop with printf/writefln, we can still default to "%s" as the default placeholder, but the {} syntax now no longer assumes printf syntax, making i"" literals MUCH more useful in many more places outside the purvey of printf/writefln. So you'd do SQL strings like this: string name; int serial; float cost; db.exec(i"INSERT INTO mytable VALUES (${?}name, ${?}serial, ${?}cost)"); which translates the last line to: db.exec("INSERT INTO mytable VALUES (?, ?, ?)", name, serial, cost); without the need for any intermediate format string parser.OK, this is definitely a winner, way better than my idea. Only thing better would be some way to set the default specifier to avoid all the verbosity. Please make this part of the DIP Walter! -Steve
Dec 11 2019
On 12/11/19 5:49 PM, Steven Schveighoffer wrote:OK, this is definitely a winner, way better than my idea. Only thing better would be some way to set the default specifier to avoid all the verbosity.Hm... heredoc gives us a precedent that might be valuable here. e.g.: db.exec(i"{?}INSERT INTO mytable VALUES ($name, $serial, $cost)") printf(i"{%d}I ate $apples and $bananas totaling $(apples + bananas) fruit.\n"); -Steve
Dec 11 2019
On 2019-12-11 22:55:22 +0000, Steven Schveighoffer said:On 12/11/19 5:49 PM, Steven Schveighoffer wrote:Yes, much better to reduce syntax-cluttering. Why not lean towards existing syntax from templates: i(?)"INSERT INTO mytable VALUES ($name, $serial, $cost)" or even make it more configurable to catch more cases: i($,?)"INSERT INTO mytable VALUES ($name, $serial, $cost)" By provding a standard case, where the printf relevant type is automatically deduced from the used variables, when no specification is given the syntax would be simple in a lot of cases: i"I ate $apples and $bananas totaling $(apples + bananas) fruit.\n" -- Robert M. Mnch http://www.saphirion.com smarter | better | fasterOK, this is definitely a winner, way better than my idea. Only thing better would be some way to set the default specifier to avoid all the verbosity.Hm... heredoc gives us a precedent that might be valuable here. e.g.: db.exec(i"{?}INSERT INTO mytable VALUES ($name, $serial, $cost)") printf(i"{%d}I ate $apples and $bananas totaling $(apples + bananas) fruit.\n"); -Steve
Dec 13 2019
On 12/13/2019 1:17 AM, Robert M. Münch wrote:Yes, much better to reduce syntax-cluttering. Why not lean towards existing syntax from templates: i(?)"INSERT INTO mytable VALUES ($name, $serial, $cost)" or even make it more configurable to catch more cases: i($,?)"INSERT INTO mytable VALUES ($name, $serial, $cost)"Too complex for too little gain.
Dec 14 2019
On Wednesday, 11 December 2019 at 22:49:01 UTC, Steven Schveighoffer wrote:On 12/11/19 5:37 PM, H. S. Teoh wrote:[…]Isn’t https://forum.dlang.org/post/vxzqttydlvzngrwrvipa forum.dlang.org better still? Streamlining template mixins could pay off in many more places, and is truly extendable and customisable. Bastiaani"$abc" == tuple("%s", abc); i"$({%d}abc)" == tuple("%d", abc); i"$({?}abc)" == tuple("?", abc); For convenient interop with printf/writefln, we can still default to "%s" as the default placeholder, but the {} syntax now no longer assumes printf syntax, making i"" literals MUCH more useful in many more places outside the purvey of printf/writefln. So you'd do SQL strings like this: string name; int serial; float cost; db.exec(i"INSERT INTO mytable VALUES (${?}name, ${?}serial, ${?}cost)"); which translates the last line to: db.exec("INSERT INTO mytable VALUES (?, ?, ?)", name, serial, cost); without the need for any intermediate format string parser.OK, this is definitely a winner, way better than my idea. Only thing better would be some way to set the default specifier to avoid all the verbosity. Please make this part of the DIP Walter!
Dec 11 2019
On Wednesday, 11 December 2019 at 23:09:01 UTC, Bastiaan Veelo wrote:Isn’t https://forum.dlang.org/post/vxzqttydlvzngrwrvipa forum.dlang.org better still? Streamlining template mixins could pay off in many more places, and is truly extendable and customisable.Seems I’m mixing up template and string mixins.
Dec 11 2019
On 12/11/2019 2:49 PM, Steven Schveighoffer wrote:Only thing better would be some way to set the default specifier to avoid all the verbosity.Since that would require some extra syntax for each i string literal, it's not worth it.
Dec 14 2019
On 12/14/19 3:56 AM, Walter Bright wrote:On 12/11/2019 2:49 PM, Steven Schveighoffer wrote:It doesn't actually i"$apples and $bananas" would still work. The default specifier is optional, just like format specifier parameters e.g. %02x have an optional 02. The only time extra syntax would be required is if you start with a brace and want to keep the default. i`{"name" : $name}`.format; // JSON interpolated object. This would result in a confusion because of the initial brace. (I'm assuming here that we can use all the different quote types for convenience) BUT 1. You can just do i`{}{"name": $name}`.format; i` {"name": $name}`.format; // taking advantage of the JSON grammar. i`{%s}{"name": $name}`.format; // respecify default 2. Or if we have your proposal of allowing string concatenation (I'll respond to that separately), then (i"{}" `{"name": $name}`).format should work, and doesn't look terrible. Normally an interpolated string will not have any need for the default alteration, and you won't notice it. I have some SQL strings with 10 or more fields, which would be super-verbose to continually put {?} or to maybe forget one! If there is a better default specifier sequence that you would accept, that would be fine too. -SteveOnly thing better would be some way to set the default specifier to avoid all the verbosity.Since that would require some extra syntax for each i string literal, it's not worth it.
Dec 14 2019
On 12/14/2019 6:36 AM, Steven Schveighoffer wrote:[...]It wouldn't be used enough to make it worthwhile. The extra syntax necessary also requires yet another means to distinguish it from the rest of the string.
Dec 14 2019
On 12/11/2019 2:37 PM, H. S. Teoh wrote:1) Change the interpretation of `%({X}varname)` to mean "use `X` instead of %s as placeholder in output string", rather than "use `%X` ...". I.e.: i"%abc" == tuple("%s", abc); i"%({%x}abc)" == tuple("%x", abc); i"%({?}abc)" == tuple("?", abc); // bingo, SQL syntax! 2) Then, in light of the %%%% problem, and to fix the repeated % in "%{%x}abc", change the default metacharacter to something like $: i"$abc" == tuple("%s", abc); i"$({%d}abc)" == tuple("%d", abc); i"$({?}abc)" == tuple("?", abc);I agree, except don't need the extra ( ).
Dec 14 2019
On 12/11/2019 12:38 PM, Steven Schveighoffer wrote:This is very much focused on writef and printf. What about other functions that accept similar string + arg tuple, but don't use %s specifiers? Perfect example is SQL: query("select * from sometable where date < ?", someDate); With the interpolation string: query(i"select * from sometable where date < %someDate"); This translates to: query("select * from sometable where date < %s", someDate); which is not correct SQL syntax.It's a great point. I propose a modification: Change the `{FormatString}` from being a suffix to `%` to being the whole format string, i.e. instead of `%{d}` make it `%{%d}`. Then, your example becomes: query("select * from sometable where date < %{?}someDate"); which gets rewritten to: query("select * from sometable where date < ?", someDate); and voila, any format specifier can be used. Robert brought up an additional problem: printf("%.*s", length, ptr); as not being representable as an interpolated string. But this change will allow it to work: printf(i"%{%.*}length%{s}ptr"); The default format will remain `%s`, as I expect that will be the vast bulk of uses.The other problem is that you are using % for the interpolated fields. This is quite puzzling, considering that the main target (printf and writef) uses % as the format specifier. Why not just change the specifier to $ or {} or \() or \{} or literally any of the other interpolation systems out there.I've decided to change it to $. That looks nice. The \ ones just look awful, and {} leaves open the problem of where to put the user-specified format.If we can think of a way to hook the string generation and have the parameters come afterwards, that would be ideal.Lowering it to a tuple is good enough. You can do whatever you wish with the resulting tuple (like pass it to a template).
Dec 14 2019
On 12/14/19 3:51 AM, Walter Bright wrote:It's a great point. I propose a modification: Change the `{FormatString}` from being a suffix to `%` to being the whole format string, i.e. instead of `%{d}` make it `%{%d}`....I've decided to change it to $. That looks nice. The \ ones just look awful, and {} leaves open the problem of where to put the user-specified format.Thanks! That's much better -Steve
Dec 14 2019
On Wednesday, 11 December 2019 at 09:52:21 UTC, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1027, "String Interpolation": https://github.com/dlang/DIPs/blob/148001a963f5d6e090bb6beef5caf9854372d0bc/DIPs/DIP1027.mdQuestions for the rationale: 1. Why % as a format character? I would guess "so that legacy strings won't accidentally trigger interpolation", but since this proposal already requires i"" syntax, legacy strings aren't a problem. Or "wanting to specify the formatting, as with %{d}bananas, meant I had to come up with something new anyway." But Nim, Zig, and Python all do this (the first two as normal library functionality rather than a language extension) with the {} syntax. import strformat let num = 123 Alternate syntax ({} interpolation): writefln(i"I ate {apples} and {bananas:d} totalling {apples + bananas} fruit."); 2. Why i"" syntax? It (presumably, not necessarily) conflicts with user string prefixes, and since this proposal already limits string interpolation to printf-style uses, and since the use of % format character already makes conflict with legacy strings already very unlikely, why not use regular string syntax but make writefln() and friends statically analyze the string they're given to see if it's an interpolating one or not? Alternate syntax (no i""; in(isTemplated!argstring)): writefln("I ate %apples and %{d}bananas totalling %(apples + bananas) fruit."); 3. Why rewrite to positional code? I would guess "because I don't want to add new GC-reliant features", but since this proposal already limits string interpolation to printf-style uses, the function accepting the string is an obvious owner. The positional rewrite has other problems: a. interpolated strings can't be mixed with conventional elements, a common and unremarkable thing for interpolation in other languages. b. functions that accept an interpolated string have to know that they do this, and have special handling for it, when in other languages the choice to interpolate is purely a decision of the caller's, and can be changed for readability or efficiency or taste. c. Speaking of efficiency: in other languages you can hoist a repeated use of an interpolated string above some loops that use it. With this proposal you'd have to rely on the optimizer to deal with this. 4. Seriously, why rewrite to positional code? This is going to function as something like an attractive nuisance for people that learn D. Newbie: "Hey, I want some interpolation here. Does D have that? Oh! It does!" Newbie: *uses interpolation, gets error* Newbie: "what?" Newbie: ... this D thing, it's filled with features with strange limitations. Features that don't work naturally together. Come on even a simple thing like string interpolation! That's convenient in every language that has it! Why is it so weird here? This is just like how the other day I tried to rewrite a trivial benchmark in -betterC and kept getting weird errors about TypeInfos. grumble grumble grumble. *** meanwhile, in a world without interpolation *** Newbie: "Hey, I want some interpolation here. Does D have that? ... looks like format() does what I want." Newbie: *uses format(), it works as expected, life moves on* -- Final "but since this proposal already" count: 3
Dec 11 2019
On Wednesday, 11 December 2019 at 23:33:20 UTC, mipri wrote:This is going to function as something like an attractive nuisance for people that learn D. Newbie: "Hey, I want some interpolation here. Does D have that? Oh! It does!" Newbie: *uses interpolation, gets error*I think there's a general rule here: A DIP that adds an innovative feature, or which enters poorly-explored design space, can be a conservative "80% solution" that has some caveats and limitations on its use, that people learning the language will need to learn to properly use the feature. But a DIP that adds a very well explored feature should provide a 100% solution that adds exactly what people will expect from "<feature name> in <any language>". It should do this precisely because people are so well-prepared in their expectations for any such feature. Suppose that D didn't have floating point numbers, and a DIP were released today to add them to the language, but instead of IEEE floating point, it implemented some novel thing. The details of the novel thing don't matter: it's not 100% what people want from "floating point", so it's an embarrassment. Think of how the documentation would have to read. dlang.org's own docs, to be useful, would have to explain the feature in terms of how it fails to meet the expectations of other languages. In code, this must all work: auto s1 = i"I ate %apples and %{d}bananas."; enum pears = "two"; enum s2 = i"I ate %pears."; immutable string s3 = i"%s1"; void takes_a_normal_string(string s) { } takes_a_normal_string(i"%one + %two = %(one + two)."); // not an error: writefln sees %d in the post-interpolation // string and works normally writefln(i"making %bread using %%d ingredients", 6); string x = qi"SPAM Hello %firstname %lastname! ... SPAM"; Although if i"" is definitely the syntax used, then the rest of the syntax is free to be something familiar like // resembles 14 languages from wikipedia examples i"$one + $two = ${one + two}" or // resembles 4 languages i"{one} + {two} = {one + two}" Finally, look at Swift's syntax: let apples = 4 print("I have \(apples) apples") How about that? Undefined escape sequences are an error, so new ones can be added without breaking the language or changing the meaning of old code. And this no longer requires an ugly 'i' prefix. If the "lower to printf-style arguments" is really what's wanted, then it could be an *option* with an alternate escape like \[apples], so people's expectations about string interpolation would still be met. A 100% solution + some extra features is a much easier sell.
Dec 11 2019
On Thursday, 12 December 2019 at 07:30:19 UTC, mipri wrote:A DIP that adds an innovative feature, or which enters poorly-explored design space, can be a conservative "80% solution" that has some caveats and limitations on its use, that people learning the language will need to learn to properly use the feature.Yes, the requirement should be that it has been implemented as a library mixin and has been popular in usage for a long time. Only then should new syntax be added for it.
Dec 12 2019
On Thursday, 12 December 2019 at 07:30:19 UTC, mipri wrote:How about that? Undefined escape sequences are an error, so new ones can be added without breaking the language or changing the meaning of old code. And this no longer requires an ugly 'i' prefix.That is a really good point! But, what about token strings? mixin(q{ auto ${functionName}() { return ${varName}; } });
Dec 12 2019
On Thursday, 12 December 2019 at 07:30:19 UTC, mipri wrote:A DIP that adds an innovative featureThis could be an innovative feature. I see very little value in traditional string interpolation and I'd vote no on that. But these tuple ones are interesting and can do things unique to D... if we do it right.In code, this must all work: auto s1 = i"I ate %apples and %{d}bananas.";If that works, you've lost my support. Note that with my proposal string s1 = i"I ate %apples and %{d}bananas."; could work though. auto and string are different - with string it can trigger `alias this`. but if it is just plain string given from the compiler, we've gained nothing of interest. Even javascript's interpolation has more metaprogramming potential than that. Do we want to lose to javascript? BTW the JS one is actually quite interesting. It calls a user-defined function, passing the arguments - similar to the D tuple thing.
Dec 12 2019
On Thursday, 12 December 2019 at 13:36:38 UTC, Adam D. Ruppe wrote:BTW the JS one is actually quite interesting. It calls a user-defined function, passing the arguments - similar to the D tuple thing.Except you can actually assign it to a string?
Dec 12 2019
On Thu, Dec 12, 2019 at 03:41:54PM +0000, aliak via Digitalmars-d wrote:On Thursday, 12 December 2019 at 13:36:38 UTC, Adam D. Ruppe wrote:[...] As Adam already said, you can assign it to a string if the return type has alias this to string. T -- One reason that few people are aware there are programs running the internet is that they never crash in any significant way: the free software underlying the internet is reliable to the point of invisibility. -- Glyn Moody, from the article "Giving it all away"BTW the JS one is actually quite interesting. It calls a user-defined function, passing the arguments - similar to the D tuple thing.Except you can actually assign it to a string?
Dec 12 2019
On Thursday, 12 December 2019 at 16:46:06 UTC, H. S. Teoh wrote:On Thu, Dec 12, 2019 at 03:41:54PM +0000, aliak via Digitalmars-d wrote:So i"blah %var" would not return a tuple but a type that has alias this to string? Like: struct interolation_type { alias ?? this; }On Thursday, 12 December 2019 at 13:36:38 UTC, Adam D. Ruppe wrote:[...] As Adam already said, you can assign it to a string if the return type has alias this to string. TBTW the JS one is actually quite interesting. It calls a user-defined function, passing the arguments - similar to the D tuple thing.Except you can actually assign it to a string?
Dec 12 2019
On Thursday, 12 December 2019 at 16:50:47 UTC, aliak wrote:So i"blah %var" would not return a tuple but a type that has alias this to string? Like:Yup that's my proposal: http://dpldocs.info/this-week-in-d/Blog.Posted_2019_05_13.html Walter's proposal isn't bad, though mine is better :) However I would tweak one thing about mine. Before I said "auto arg1 = 50; ". I'd actually change that now to `auto arg1 = () => 50;` for more compile time / runtime mixing compatibility. I might also steal the raw string thing from Javascript... and I actually kinda like the format string from Walter's proposal, though mine can actually do that too already by reading format stuff in CTFE right out of the string.
Dec 12 2019
On Thursday, 12 December 2019 at 17:05:32 UTC, Adam D. Ruppe wrote:On Thursday, 12 December 2019 at 16:50:47 UTC, aliak wrote:Quite better solution in my opinion. AndreaSo i"blah %var" would not return a tuple but a type that has alias this to string? Like:Yup that's my proposal: http://dpldocs.info/this-week-in-d/Blog.Posted_2019_05_13.html
Dec 13 2019
On Friday, 13 December 2019 at 09:19:53 UTC, Andrea Fontana wrote:On Thursday, 12 December 2019 at 17:05:32 UTC, Adam D. Ruppe wrote:Yes, I would also like a dip with the Adam proposalOn Thursday, 12 December 2019 at 16:50:47 UTC, aliak wrote:Quite better solution in my opinion. AndreaSo i"blah %var" would not return a tuple but a type that has alias this to string? Like:Yup that's my proposal: http://dpldocs.info/this-week-in-d/Blog.Posted_2019_05_13.html
Dec 13 2019
On Thursday, 12 December 2019 at 17:05:32 UTC, Adam D. Ruppe wrote:On Thursday, 12 December 2019 at 16:50:47 UTC, aliak wrote:Ah ok. Yeah that sounds pretty good! I'm starting to wonder now, what's the use case for returning tuples? Why not just a string?So i"blah %var" would not return a tuple but a type that has alias this to string? Like:Yup that's my proposal: http://dpldocs.info/this-week-in-d/Blog.Posted_2019_05_13.html Walter's proposal isn't bad, though mine is better :) However I would tweak one thing about mine. Before I said "auto arg1 = 50; ". I'd actually change that now to `auto arg1 = () => 50;` for more compile time / runtime mixing compatibility. I might also steal the raw string thing from Javascript... and I actually kinda like the format string from Walter's proposal, though mine can actually do that too already by reading format stuff in CTFE right out of the string.
Dec 16 2019
On Mon, Dec 16, 2019 at 11:00:34AM +0000, aliak via Digitalmars-d wrote: [...]I'm starting to wonder now, what's the use case for returning tuples? Why not just a string?For generating injection-proof SQL, for one thing. Probably others. T -- GEEK = Gatherer of Extremely Enlightening Knowledge
Dec 16 2019
On Thursday, 12 December 2019 at 15:41:54 UTC, aliak wrote:Except you can actually assign it to a string?The javascript version is allowed to return whatever it wants. The default one returns string but you can do other things with it too like return objects or functions or whatever. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals It passes the strings and the original elements, and you can actually even request the raw string to do custom escape sequences in it (really, the JS lexer treats it as a raw string, then there's a function on the object that can do default escape sequences for you). If you wanna talk about taking the best ideas from other languages, Javascript's template literals are actually really nice. They are so much more than a multi-line string or a way to concatenate things. This is why my proposal transforms the "interpolated string" into an object. Making it do the raw string with an escape method is a good idea to take too. Anyway, the object can `alias toString this` so you assign it to string and it just works like newbies expect. Templates don't trigger alias this but do often use toString so that just works. But then you can also recognize it specifically in functions/templates, store it in variables, etc for further processing. My interpolation object can be transformed into a ("%s", x) tuple. A plain tuple for calls like writeln. Or be passed to user functions. XmlElement e = xml!i" "; There's a lot of cool things we can do.
Dec 12 2019
On Thursday, 12 December 2019 at 17:01:01 UTC, Adam D. Ruppe wrote:On Thursday, 12 December 2019 at 15:41:54 UTC, aliak wrote:It'd be great if you could expand on this with a list of examples of what D could do.[...]The javascript version is allowed to return whatever it wants. The default one returns string but you can do other things with it too like return objects or functions or whatever. [...]
Dec 12 2019
On Thursday, 12 December 2019 at 17:03:53 UTC, Atila Neves wrote:On Thursday, 12 December 2019 at 17:01:01 UTC, Adam D. Ruppe wrote:Tagged template literals are indeed quite nice in JS. Here's an example from the chalk npm package [1]: ```js // Plain template literals (a.k.a. built-in string interpolation): const str1 = ` CPU: ${chalk.red("90%")} RAM: ${chalk.green("40%")} DISK: ${chalk.yellow("70%")} `; // Same example but with tagged template literals - more DRY: const str2 = chalk` CPU: {red 90%} RAM: {green 40%} DISK: {yellow 70%} `; // Tagged template literals + interpolation of variables: const cpu = 90; const ram = 40; const disk = 70; const str3 = chalk` CPU: {red ${cpu}%} RAM: {green ${ram}%} DISK: {yellow ${disk}%} `; Here's another example, this case from the es2015-i18n-tag library [2] that applies translations, locale and currency formatting: const name = 'Steffen' const amount = 1250.33 console.log(i18n`Hello ${ name }, you have ${ amount }:c in your bank account.`) // Hallo Steffen, Sie haben US$ 1,250.33 auf Ihrem Bankkonto. ``` The D analog of a function that can be used as tagged template string literal would be: ```d string interpolate(Args...)(string[] parts, Args args) { import std.algorithm.iteration : joiner; import std.conv : text; import std.range : roundRobin; string[Args.length] stringifiedArgs; static foreach (idx, arg; args) stringifiedArgs[idx] = text(arg); return parts.roundRobin(stringifiedArgs[]).joiner.text; } static import term; // Assume some ANSI term coloring library const string res = i" CPU: ${term.red("90%")} RAM: ${term.green("40%")} DISK: ${term.yellow("70%")} ".interpolate; ``` [1]: https://github.com/chalk/chalk [2]: https://github.com/skolmer/es2015-i18n-tagOn Thursday, 12 December 2019 at 15:41:54 UTC, aliak wrote:It'd be great if you could expand on this with a list of examples of what D could do.[...]The javascript version is allowed to return whatever it wants. The default one returns string but you can do other things with it too like return objects or functions or whatever. [...]
Dec 12 2019
On Thursday, 12 December 2019 at 23:31:21 UTC, Petar Kirov [ZombineDev] wrote:On Thursday, 12 December 2019 at 17:03:53 UTC, Atila Neves wrote:With no changes to DIP-1027: const str1 = format(i" CPU: %(chalk.red("90%")) RAM: %(chalk.green("40%")) DISK: %(chalk.yellow("70%")) "); which lowers to const str1 = format(" CPU: %s RAM: %s DISK: %s ", chalk.red("90%"), chalk.green("40%"), chalk.yellow("70%"));It'd be great if you could expand on this with a list of examples of what D could do.Tagged template literals are indeed quite nice in JS. Here's an example from the chalk npm package [1]: ```js // Plain template literals (a.k.a. built-in string interpolation): const str1 = ` CPU: ${chalk.red("90%")} RAM: ${chalk.green("40%")} DISK: ${chalk.yellow("70%")} `;// Same example but with tagged template literals - more DRY: const str2 = chalk` CPU: {red 90%} RAM: {green 40%} DISK: {yellow 70%} `;Likewise: with (chalk) { const str2 = format(i" CPU: %(90.percent.red) RAM: %(40.percent.green) DISK: %(70.percent.yellow) "); }// Tagged template literals + interpolation of variables: const cpu = 90; const ram = 40; const disk = 70; const str3 = chalk` CPU: {red ${cpu}%} RAM: {green ${ram}%} DISK: {yellow ${disk}%} `;Likewise: with (chalk) { const str2 = format(i" CPU: %(cpu.red) RAM: %(ram.green) DISK: %(disk.yellow) "); }Here's another example, this case from the es2015-i18n-tag library [2] that applies translations, locale and currency formatting: const name = 'Steffen' const amount = 1250.33 console.log(i18n`Hello ${ name }, you have ${ amount }:c in your bank account.`) // Hallo Steffen, Sie haben US$ 1,250.33 auf Ihrem Bankkonto. ```Likewise: writeln(i18n(i"Hello %name, you have %{$}(amount) in your bank account.")); which lowers to: writeln(i18n("Hello %s, you have %$ in your bank account.", name, amount)); and normal function i18n can do the gettext() stuff, and handle %$ itself, or indeed it could do nothing special with %$ but leave it to custom format specifiers and `amount` being a monetary object: https://wiki.dlang.org/Defining_custom_print_format_specifiers So I must conclude: 1. This is all very cool, but 2. DIP-1027 can do all of it as currently specified. 3. Actually DIP-1027 is not as bad as I thought. In particular, instead of documenting the feature in terms of its failures vs. other languages, it can say "use format() if you mainly to build a string" and "here's some cool stuff that this design lets you do, that more traditional string interpolation could not do." So I respectfully withdraw my complaints and instead submit support for some kind of SQL generalization with ? placeholders.
Dec 12 2019
On Friday, 13 December 2019 at 00:05:54 UTC, mipri wrote:3. Actually DIP-1027 is not as bad as I thought. In particular, instead of documenting the feature in terms of its failures vs. other languages, it can say "use format() if you mainly to build a string" and "here's some cool stuff that this design lets you do, that more traditional string interpolation could not do."To be clear, some cool stuff is 1. Internationalization. Normally with string interpolation in languages, the interpolation happens before anything can see the string, so f.e. the Perl way to do internationalization is just printf(gettext("I scanned %g %s."), $dir_scan_count, $dir_scan_count == 1 ? gettext("directory") : gettext("directories"), ); https://metacpan.org/pod/Locale::Maketext::TPJ13 despite "I scanned $count $directory" being the more normal way to write that code in Perl. 2. SQL queries without SQL injection, if support for this is added. It's precisely due to the popularity of string interpolation that SQL injection even happens, and so again the Perl way to do database queries is my $contained_sql = <<""; SELECT id FROM city_buildings WHERE minLong >= ? AND maxLong <= ? AND minLat >= ? AND maxLat <= ? my $contained = $dbh->selectcol_arrayref($contained_sql,undef, $minLong, $maxLong, $minLat, $maxLat); https://metacpan.org/pod/DBD::SQLite Normally, string interpolation is a convenience that you can use most of the time but have to put aside when things get advanced. Here we have a proposed string interpolation that fits the most common case while still being useful in more advanced cases, which is instead a slightly less convenient in certain cases. The most common case: writeln("Hello, %s.".format(name)); // currently writefln(i"Hello, %name."); // DIP-1027 println("Hello, $name."); // Kotlin An advanced case: writeln(format(_("Hello, %s!"), name)); // currently (djtext) writeln(i"Hello, %name!".nu_gettext); // DIP-1027 // I can't find a Kotlin example. An inconvenient case: // currently string[] greetings = [ "Hello, %s".format(name), "Aloha, %s".format(name), "Hiya, %s".format(name), "Salutations, %s".format(name), ]; // DIP-1027 string[] greetings = [ i"Hello, %name".format, i"Aloha, %name".format, i"Hiya, %name".format, i"Salutations, %name".format, ]; // Kotlin val greetings = listOf( "Hello, $name", "Aloha, $name", "Hiya, $name", "Salutations, $name" ) Note the 'nu_gettext'. It can't be djtext's existing _() or getdtext() functions because you can't accept the i"" string without also accepting the parameters for the i"" string.
Dec 12 2019
On Thursday, 12 December 2019 at 17:03:53 UTC, Atila Neves wrote:It'd be great if you could expand on this with a list of examples of what D could do.Of course, there's the examples of printf, writeln, sql query.. (One other addition I might make to my proposal is having the string version of what's in the thing too, but I digress). Those are the easy ones. Note btw that you can even do a format!"%s"(a) type thing. But it can get pretty interesting to look beyond function calls. What about some kind of object literal? int a; string b; JSONValue j = json!iq{ }; That specific syntax assumes interpolated token strings are a thing but it could just as well be JSONValue j = json!i" "; or %(a) or $a or whatever. I don't care. The implementation would look something like: JSONValue json(__d_interpolated_string s)() { JSONValue j; foreach(idx, member; s.tupleof) { static if(!(idx & 1)) { j.object[member.replace(",", "").strip] = JSONValue(member[idx + 1]()); } } return j; } you know plus more sanity but you get the idea. All the data is in an object which we can pass to a template to do compile time checking and return type processing etc. Of course, for json, you can do a built in AA and a constructor from it, just then the types have to be heterogeneous. Not a huge deal for json but it can get ugly nested. But we can do xml too, think react's jsx int foo; string bar = "<"; Element e = jsx!i` `; assert(e.tagName = "foo"); assert(e.attrs.value == foo); assert(e.innerHTML == "<"); This is almost interchangeable with the mixin(foo!"string") thing... in fact you could implement it that way, just instead of having foo!xx return a code string the compiler helps a bit more.
Dec 12 2019
On Friday, 13 December 2019 at 00:06:15 UTC, Adam D. Ruppe wrote:But it can get pretty interesting to look beyond function calls. What about some kind of object literal? int a; string b; JSONValue j = json!iq{ };This doesn't work though: auto n = 4; [1,2,3].map!(format("a + %s", n)).each!writeln; // Error: variable n cannot be read at compile time It doesn't even work to pass that format() to void ignore(string s)() { } So I imagine i"" strings won't be useful in static arguments except with static parameters.
Dec 12 2019
On Friday, 13 December 2019 at 01:19:32 UTC, mipri wrote:This doesn't work though: auto n = 4; [1,2,3].map!(format("a + %s", n)).each!writeln;Indeed, but it does work to pass seq!(() => n). That's why I've amended my proposal to do that instead. Then it inherits the CT-ness of n while still being usable in a runtime context. It is similar to `lazy` parameters built into the language;So I imagine i"" strings won't be useful in static arguments except with static parameters.auto interpolate(T...)() { import std.conv; string s; foreach(t; T) static if(is(typeof(t) == string)) s ~= t; else s ~= to!string(t()); return s; } void main() { int n; enum n2 = 56; // runtime variable works for runtime, but errors if `enum s;` string s = interpolate!("this works: ", () => n); // CT variable works in either cse enum e = interpolate!("this works too ", () => n2); import std.stdio; writeln(s); writeln(e); } In my original proposal I was just going to use a value, but the compiler-generated lambda is more flexible as seen here. So becomes __DInterpolatedString!("foo ", () => a); and you can do all kinds of magical things with that. (In my original proposal I rejected this hybrid library solution because of this very problem, but this little bit of magic allows it. The compiler simply rewrites the i"" string into a call to that template, then object.d can be responsible for doing the rest.) If you like I could actually go ahead and write up a library implementation and we pretend the syntax lowering is in place to evaluate it.
Dec 12 2019
On 13.12.19 02:30, Adam D. Ruppe wrote:On Friday, 13 December 2019 at 01:19:32 UTC, mipri wrote:I think that's a bit hacky, e.g.: int x=0; auto s=i"$(++x)"; writeln(s); // 1 writeln(s); // 2This doesn't work though: auto n = 4; [1,2,3].map!(format("a + %s", n)).each!writeln;Indeed, but it does work to pass seq!(() => n). That's why I've amended my proposal to do that instead. Then it inherits the CT-ness of n while still being usable in a runtime context. It is similar to `lazy` parameters built into the language;
Dec 12 2019
On Friday, 13 December 2019 at 02:10:04 UTC, Timon Gehr wrote:I think that's a bit hacky, e.g.:yeah, can fix that with a lazily initialized cache. but if it is built into the compiler we can fix details like this there too.
Dec 12 2019
On Thursday, 12 December 2019 at 17:01:01 UTC, Adam D. Ruppe wrote:On Thursday, 12 December 2019 at 15:41:54 UTC, aliak wrote:That is a good observation. I forgot all about tagged template literals. We should totally steal some of that. From the page:Except you can actually assign it to a string?The javascript version is allowed to return whatever it wants. The default one returns string but you can do other things with it too like return objects or functions or whatever. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literalsTemplate literals are enclosed by the back-tick (` `) (grave accent) character instead of double or single quotes. Template literals can contain placeholders. These are indicated by the dollar sign and curly braces (${expression}). The expressions in the placeholders and the text between the back-ticks (` `) get passed to a function. The default function just concatenates the parts into a single string. If there is an expression preceding the template literal (tag here), this is called a "tagged template". In that case, the tag expression (usually a function) gets called with the template literal, which you can then manipulate before outputting.try this in your browser's console: val = 4; function sql(strings, ...keys) { return {sql: strings.join("?"), keys} }; sql`select * from table where a = ${val} and b = ${val}`; it will return: {"sql":"select * from table where a = ? and b = ?","keys":[4,4]}If you wanna talk about taking the best ideas from other languages, Javascript's template literals are actually really nice. They are so much more than a multi-line string or a way to concatenate things.yes.
Dec 12 2019
I find your proposal a little confusing. By turning the string into an object, it doesn't work with printf? I'm also not sure it's a good idea to make this more powerful. As a simple "replace the string with a tuple" its very easy to understand.
Dec 14 2019
On 2019-12-14 10:10, Walter Bright wrote:I find your proposal a little confusing. By turning the string into an object, it doesn't work with printf?One would need to explicitly call `toString` or add an `alias this` to the struct. -- /Jacob Carlborg
Dec 14 2019
On Saturday, 14 December 2019 at 09:10:47 UTC, Walter Bright wrote:I find your proposal a little confusing. By turning the string into an object, it doesn't work with printf?Right, not directly. But then it is trivial to add a member of the object that transforms it into a tuple suitable for printf. So the end user's code now looks like: `printf(i"foo %bar".asFormatTuple);` BTW I am not opposed to your version either, since it can be transformed into something close to my version. My big concern is that your version (as well as Jonathan Marler's) loses information very easily. printf(i"%item"); // happens to work writefln(i"%item"); // also happens to work writeln(i"%item"); // oops! not going to do what you want format(); // works text(); // wrong And there's no compile error for incorrect usage. With an object, we get existing type checking safety and can guide it to the correct usage: printf(i""); // error cannot implicitly convert __d_interpolated_string to const char* writefln(i""); // static assert failed: "use i"".asFormatTuple instead writeln(i""); // happens to just work because it calls toStringI'm also not sure it's a good idea to make this more powerful. As a simple "replace the string with a tuple" its very easy to understand.Objects are easy to understand too. And easy to implement: on the compiler it is basically just `X!(your version)` instead of just plain `(your version)`.
Dec 14 2019
On 12/14/19 9:23 AM, Adam D. Ruppe wrote:On Saturday, 14 December 2019 at 09:10:47 UTC, Walter Bright wrote:What information does it lose?I find your proposal a little confusing. By turning the string into an object, it doesn't work with printf?Right, not directly. But then it is trivial to add a member of the object that transforms it into a tuple suitable for printf. So the end user's code now looks like: `printf(i"foo %bar".asFormatTuple);` BTW I am not opposed to your version either, since it can be transformed into something close to my version. My big concern is that your version (as well as Jonathan Marler's) loses information very easily.printf(i"%item"); // happens to work writefln(i"%item"); // also happens to work writeln(i"%item"); // oops! not going to do what you wantBut did what you asked? Coding is full of such dilemmas. I've actually done this many many times: writeln("Value is %s", value); I see the result, and fix it. This isn't difficult. One other suggestion I had was to make the resulting string literal generated by interpolation be a derivative of a string literal. That is, it's usable wherever a string literal is, but functions that wish to overload based on that type difference can do so. i.e. we could make the writeln call above work as expected.format(); // works text(); // wrong And there's no compile error for incorrect usage. With an object, we get existing type checking safety and can guide it to the correct usage: printf(i""); // error cannot implicitly convert __d_interpolated_string to const char*Hm... I prefer it just working correctly.writefln(i""); // static assert failed: "use i"".asFormatTuple insteadSame. But why wouldn't writefln be overloaded on your object type to do the right thing?writeln(i""); // happens to just work because it calls toStringSure, but if you are going through the trouble to deal with format specifiers, I don't know why you'd want to support writeln out of the box but not writefln. Not only that, but now you have to pull a lot of the library into druntime (std.format for example).What about the lifetime issues? An object is going to make a copy. Which may not be correct or possible. I do like two aspects of your proposal. First is that all the information is available for further compile-time manipulation. Second is that having a specialized type allows function overloading. -SteveI'm also not sure it's a good idea to make this more powerful. As a simple "replace the string with a tuple" its very easy to understand.Objects are easy to understand too. And easy to implement: on the compiler it is basically just `X!(your version)` instead of just plain `(your version)`.
Dec 14 2019
On Saturday, 14 December 2019 at 15:04:24 UTC, Steven Schveighoffer wrote:What information does it lose?The grouping of the items in the string. Tuples auto-flatten and then the function cannot tell any more if they actually were together to begin with. The format string lets you reconstruct it though, assuming you know to check for a format string. This is why I can work with Walter's proposal, it would just be disappointing to lose the overloading aspect of it.One other suggestion I had was to make the resulting string literal generated by interpolation be a derivative of a string literal.That's what an object with `alias toString this` is!Hm... I prefer it just working correctly.We can do that with Phobos functions (and indeed anything written after we decide on the interface), but printf's interface is already locked down, so it is either just working there or having an object, can't do both.... and I think that'd be a pity since a compile error telling you to use ".asFormatString" is such an easy solution.Not only that, but now you have to pull a lot of the library into druntime (std.format for example).Solved problem: you'd make the method templated so it is only pulled if used. The ^^ operator in D works like this already. No need to actually bring it in to druntime, it will just reference phobos iff used.What about the lifetime issues? An object is going to make a copy. Which may not be correct or possible.So does a tuple passed to a function, there's no difference here anyway. Remember, all my thing really boils down to is the compiler inserting X!T instead of just T.
Dec 14 2019
On 12/14/2019 6:23 AM, Adam D. Ruppe wrote:On Saturday, 14 December 2019 at 09:10:47 UTC, Walter Bright wrote:I was afraid that would be it. The extra syntax kills it, along with the extra import required, along with not working with #betterC. You can still #thagomize it, or turn it into an object, etc., with: Object thagomize(string, ...); ... thagomize(i"foo%bar"); It's just not the default.I find your proposal a little confusing. By turning the string into an object, it doesn't work with printf?Right, not directly. But then it is trivial to add a member of the object that transforms it into a tuple suitable for printf. So the end user's code now looks like: `printf(i"foo %bar".asFormatTuple);`
Dec 14 2019
On Sunday, 15 December 2019 at 01:44:18 UTC, Walter Bright wrote:The extra syntax kills itThis is true, but ONLY for the printf case. It just works in all other cases.with the extra import required, along with not working with #betterC.No need for import - this is a definition in object.d, and it will work in betterC since this is a compile-time transformation (the `asFormatString` definition is essentially just `template asFormatString(T...) { alias asFormatString = T; }`. And my proposal also doesn't need an import to be assigned to a string whereas yours does. string a = i""; // mine would trigger the alias toString this and just work string a = format(i""); // must import std.format. also fails in betterC btwIt's just not the default.Which is usable (that's why I'm not opposed to your proposal) but means it is now impossible to catch accidental misuses at compile time. They type system no longer helps you. But what about a small compromise: what if JUST the format string was given a new type and the rest was still a tuple. The format string can implicitly convert to the same things a string literal can; it can go to `string` or to `const char*`, but then user-defined functions are also able to overload on it. So i"hi %test" becomes basically typedef string InterpolatedFormat; type_tuple(InterpolatedFormat("hi %s"), test) That'd still work in printf - it just implicitly converts back to char* - and gives just enough type information hints to cover my advanced use cases too.
Dec 14 2019
On 12/14/2019 5:52 PM, Adam D. Ruppe wrote:On Sunday, 15 December 2019 at 01:44:18 UTC, Walter Bright wrote:printf is a very important case, and it kills it for scanf and every other function that takes a format string (dmd itself has many printf-like functions).The extra syntax kills itThis is true, but ONLY for the printf case. It just works in all other cases.object.d is getting more and more bloated over time. This is not a solution to imports, and is not a good trend.with the extra import required, along with not working with #betterC.No need for import - this is a definition in object.d,and it will work in betterC since this is a compile-time transformation (the `asFormatString` definition is essentially just `template asFormatString(T...) { alias asFormatString = T; }`. And my proposal also doesn't need an import to be assigned to a string whereas yours does. string a = i""; // mine would trigger the alias toString this and just work string a = format(i""); // must import std.format. also fails in betterC btwbetterC is for use without Phobos.That's always been true with printf. Many C compilers have extensions to deal with this, but D never incorporated them (although it could).It's just not the default.Which is usable (that's why I'm not opposed to your proposal) but means it is now impossible to catch accidental misuses at compile time. They type system no longer helps you.But what about a small compromise: what if JUST the format string was given a new type and the rest was still a tuple. The format string can implicitly convert to the same things a string literal can; it can go to `string` or to `const char*`, but then user-defined functions are also able to overload on it. So i"hi %test" becomes basically typedef string InterpolatedFormat; type_tuple(InterpolatedFormat("hi %s"), test) That'd still work in printf - it just implicitly converts back to char* - and gives just enough type information hints to cover my advanced use cases too.Adding a new basic type to the language just for this is not worth it. With the proposal, I can explain it in one slide, which is worth a great deal.
Dec 14 2019
On Sunday, 15 December 2019 at 04:20:59 UTC, Walter Bright wrote:On 12/14/2019 5:52 PM, Adam D. Ruppe wrote:IIRC you said dmd was just a direct translation from C and carries all that legacy debt. Is that really an example you want to be using to justify your point?On Sunday, 15 December 2019 at 01:44:18 UTC, Walter Bright wrote:printf is a very important case, and it kills it for scanf and every other function that takes a format string (dmd itself has many printf-like functions).The extra syntax kills itThis is true, but ONLY for the printf case. It just works in all other cases.You don't need to add an extra feature and warnings to the compiler. There's already a type system that can be used. Also that feature isn't that simple to implement. I see all the hacks to get around it in android's kernel source. They treat the warning as an error, even with the hacks in the source code. It still gives false positives and I end up disabling it or just deleting the logs that are causing the error. If it was important it would already have been implemented, but no one uses printf as there are better alternatives.That's always been true with printf. Many C compilers have extensions to deal with this, but D never incorporated them (although it could).It's just not the default.Which is usable (that's why I'm not opposed to your proposal) but means it is now impossible to catch accidental misuses at compile time. They type system no longer helps you.
Dec 14 2019
On Sunday, 15 December 2019 at 05:34:48 UTC, Jab wrote:If it was important it would already have been implemented, but no one uses printf as there are better alternatives.That's wrong, we use printf snprint and sprintf a lot since we can't use D with its runtime (makes too much problems in a shared lib) and printf still is the gold standard for conversion of float to string.
Dec 15 2019
On Sunday, 15 December 2019 at 18:29:10 UTC, Guillaume Piolat wrote:On Sunday, 15 December 2019 at 05:34:48 UTC, Jab wrote:It was a figure of speech. You are most definitely in the minority. You can create a convenience wrapper around printf that is nogc so you don't have to use it directly.If it was important it would already have been implemented, but no one uses printf as there are better alternatives.That's wrong, we use printf snprint and sprintf a lot since we can't use D with its runtime (makes too much problems in a shared lib) andprintf still is the gold standard for conversion of float to string.It's just the most accessible. There are better float to string implementations out there.
Dec 15 2019
On Sunday, 15 December 2019 at 04:20:59 UTC, Walter Bright wrote:With the proposal, I can explain it in one slide, which is worth a great deal.To use it people will need to understand how to use d tuples as well. This seems like optimizing for betterC? Why not optimize for the D case? Do you know how many users even use betterC? People will write writeln(i”$var bananas”) and see it not work, and not understand why. The most basic case doesn’t work either with this proposal (assigning a what-you-intuitively-think is a string to a string).
Dec 15 2019
On 12/15/2019 2:17 AM, Aliak wrote:To use it people will need to understand how to use d tuples as well.No, they don't.
Dec 15 2019
On Monday, 16 December 2019 at 01:35:51 UTC, Walter Bright wrote:On 12/15/2019 2:17 AM, Aliak wrote:User: why can't I do this?/Why doesn't this work? string s = i"$var"; Answer?To use it people will need to understand how to use d tuples as well.No, they don't.
Dec 16 2019
On Monday, 16 December 2019 at 10:48:51 UTC, aliak wrote:On Monday, 16 December 2019 at 01:35:51 UTC, Walter Bright wrote:because string s = ("%s",var); is a syntax error. Even a beginning programmer can understand that an interpolated string cannot be a pure simple string as it contains symbols and expressions that are language construct not part of the string literal, i.e. that the compiler has to perform some transformations to substitute these language symbols into a value. Interpolated strings, in any language, are not string literals. Each language resolves this fact in different manners and at different times. Interpreted languages do it at runtime (obviously), java like languages chose to do it at runtime. In a language like D, which prefers resolving what is resolvable at compile time, it would be loathed if it interpolation was resolved at runtime (remember how long people were bitching about runtime only format strings?) Resolving interpolation at compile time is imho incompatible with handling them as regular strings. The question is then do we want CT or RT interpolated strings. RT interpolated strings can still be provided by a library.On 12/15/2019 2:17 AM, Aliak wrote:User: why can't I do this?/Why doesn't this work? string s = i"$var"; Answer?To use it people will need to understand how to use d tuples as well.No, they don't.
Dec 16 2019
On Monday, 16 December 2019 at 11:08:00 UTC, Patrick Schluter wrote:On Monday, 16 December 2019 at 10:48:51 UTC, aliak wrote:Maybe I'm wrong here, I haven't thought it through, but in first approach I think that's an essential point. As the string contains code, if evaluated at CT, the string must be split somehow in literal parts and code parts. Allowing the i-string to be handled as regular string implies that the splitting happens sometime between when it is declared and after it is used, which can happen after runtime. import fn; int b = 20; string inter = i"$(a+b)"; foreach(a; 1..10) fn(inter); --- module fn; void fn(string s) { writefln(s); } How would that work? In python or javascript there's no issue, a is a runtime symbol.Resolving interpolation at compile time is imho incompatiblewith handling them as regular strings.The question is then do we want CT or RT interpolated strings. RT interpolated strings can still be provided by a library.
Dec 16 2019
On Monday, 16 December 2019 at 11:18:33 UTC, Patrick Schluter wrote:Maybe I'm wrong here, I haven't thought it through, but in first approach I think that's an essential point. As the string contains code, if evaluated at CT, the string must be split somehow in literal parts and code parts. Allowing the i-string to be handled as regular string implies that the splitting happens sometime between when it is declared and after it is used, which can happen after runtime. import fn; int b = 20; string inter = i"$(a+b)"; foreach(a; 1..10) fn(inter); --- module fn; void fn(string s) { writefln(s); } How would that work? In python or javascript there's no issue, a is a runtime symbol.Not sure how other languages do it but in Ruby the interpolation is performed where the string literal is declared. Not where the string is later used. So the above would fail because `a` is not available. -- /Jacob Carlborg
Dec 16 2019
On Monday, 16 December 2019 at 12:37:47 UTC, Jacob Carlborg wrote:On Monday, 16 December 2019 at 11:18:33 UTC, Patrick Schluter wrote:Yes, probably. The issue I had with the transformation as string is what should the code below print? import fn; int a, b = 20; string inter = i"$(a+b)"; for(a=0; a<10; a++) fn(inter); --- module fn; void fn(string s) { writef(s); } prints 202020202020202020 or 212223242526272829 and that's the difference between CT evaluation and RT evaluation.Maybe I'm wrong here, I haven't thought it through, but in first approach I think that's an essential point. As the string contains code, if evaluated at CT, the string must be split somehow in literal parts and code parts. Allowing the i-string to be handled as regular string implies that the splitting happens sometime between when it is declared and after it is used, which can happen after runtime. import fn; int b = 20; string inter = i"$(a+b)"; foreach(a; 1..10) fn(inter); --- module fn; void fn(string s) { writefln(s); } How would that work? In python or javascript there's no issue, a is a runtime symbol.Not sure how other languages do it but in Ruby the interpolation is performed where the string literal is declared. Not where the string is later used. So the above would fail because `a` is not available.
Dec 16 2019
On Monday, 16 December 2019 at 12:55:17 UTC, Patrick Schluter wrote:Yes, probably. The issue I had with the transformation as string is what should the code below print? import fn; int a, b = 20; string inter = i"$(a+b)"; for(a=0; a<10; a++) fn(inter); --- module fn; void fn(string s) { writef(s); } prints 202020202020202020 or 212223242526272829 and that's the difference between CT evaluation and RT evaluation.It's difficult to say as your code doesn't compile. As it's written the code will fail to compile because you cannot have a for-loop at module scope. The line where `inter` is declared would fail to compile as well because `a` and `b` cannot be read at compile time. I don't see how that would be any different compared to this code: module foo; int a, b = 20; int c = a + b; // fails to compile as well If all of this code would be wrapped in a function, then it would successfully compile. `inter` would be evaluated to "20" and the code would print: 20202020202020202020 I don't see how it would behave any differently than if you replaced `string` with `int` and removed `i"$"`. For the result to be `212223242526272829` `i"$(a+b)"` would need to be a macro. -- /Jacob Carlborg
Dec 17 2019
On Tuesday, 17 December 2019 at 09:20:06 UTC, Jacob Carlborg wrote:On Monday, 16 December 2019 at 12:55:17 UTC, Patrick Schluter wrote:Yes, and that was the point of the exercice. Transforming the interpolated "string" into a string evaluates the values of the variables at the moment of that transformation. From then on, there is no interpolation possible as it a simple string. I suppose that what aliak leant in his comments was that the string then could still be used for interpolation. hypothetic scenario of what I interpreted what aliak wanted (and it won't compile, it's just for illustration) int apple; ... string my_is = i"apple=${apple}"; ... apple = 36; writeln(my_is); would print "apple=36" with this DIP, when you do this int apple; ... string my_is = i"apple=${apple}".format; ... apple = 36; writeln(my_is); will print "apple=0" because my_is will contain the string "apple=0" The basic thing here is what Walter said above: interpolated strings are not string literals, they can't be. They are code.Yes, probably. The issue I had with the transformation as string is what should the code below print? import fn; int a, b = 20; string inter = i"$(a+b)"; for(a=0; a<10; a++) fn(inter); --- module fn; void fn(string s) { writef(s); } prints 202020202020202020 or 212223242526272829 and that's the difference between CT evaluation and RT evaluation.It's difficult to say as your code doesn't compile. As it's written the code will fail to compile because you cannot have a for-loop at module scope. The line where `inter` is declared would fail to compile as well because `a` and `b` cannot be read at compile time. I don't see how that would be any different compared to this code: module foo; int a, b = 20; int c = a + b; // fails to compile as well If all of this code would be wrapped in a function, then it would successfully compile. `inter` would be evaluated to "20" and the code would print: 20202020202020202020 I don't see how it would behave any differently than if you replaced `string` with `int` and removed `i"$"`. For the result to be `212223242526272829` `i"$(a+b)"` would need to be a macro.
Dec 17 2019
On 2019-12-17 11:14, Patrick Schluter wrote:Yes, and that was the point of the exercice. Transforming the interpolated "string" into a string evaluates the values of the variables at the moment of that transformation. From then on, there is no interpolation possible as it a simple string. I suppose that what aliak leant in his comments was that the string then could still be used for interpolation. hypothetic scenario of what I interpreted what aliak wanted (and it won't compile, it's just for illustration) int apple; ... string my_is = i"apple=${apple}"; ... apple = 36; writeln(my_is); would print "apple=36" with this DIP, when you do this int apple; ... string my_is = i"apple=${apple}".format; ... apple = 36; writeln(my_is); will print "apple=0" because my_is will contain the string "apple=0"I don't see how lowering to a tuple will change anything. It's not possible to store expressions. If you have the expression `3 + 4` than that will be evaluated and `7` is what's left. Unless the expression is wrapped in a lambda.The basic thing here is what Walter said above: interpolated strings are not string literals, they can't be. They are code.Of course they can. They can be whatever we decide them to be. -- /Jacob Carlborg
Dec 17 2019
On Tuesday, 17 December 2019 at 16:43:32 UTC, Jacob Carlborg wrote:On 2019-12-17 11:14, Patrick Schluter wrote:Which was my point. An interpolated string cannot be stored in a simple string as some people requested in the thread before (not you). It is only feasible if the istring is evaluated at runtime with an interpreter who knows the current values of the variables used. Interpreted languages like python, perl, javascript etc. might get away with it but compiled languages have to transform it in its code representation.Yes, and that was the point of the exercice. Transforming the interpolated "string" into a string evaluates the values of the variables at the moment of that transformation. From then on, there is no interpolation possible as it a simple string. I suppose that what aliak leant in his comments was that the string then could still be used for interpolation. hypothetic scenario of what I interpreted what aliak wanted (and it won't compile, it's just for illustration) int apple; ... string my_is = i"apple=${apple}"; ... apple = 36; writeln(my_is); would print "apple=36" with this DIP, when you do this int apple; ... string my_is = i"apple=${apple}".format; ... apple = 36; writeln(my_is); will print "apple=0" because my_is will contain the string "apple=0"I don't see how lowering to a tuple will change anything. It's not possible to store expressions. If you have the expression `3 + 4` than that will be evaluated and `7` is what's left. Unless the expression is wrapped in a lambda.The basic thing here is what Walter said above: interpolated strings are not string literals, they can't be. They are code.Of course they can. They can be whatever we decide them to be.
Dec 17 2019
On Tuesday, 17 December 2019 at 17:13:50 UTC, Patrick Schluter wrote:Which was my point. An interpolated string cannot be stored in a simple string as some people requested in the thread before (not you). It is only feasible if the istring is evaluated at runtime with an interpreter who knows the current values of the variables used. Interpreted languages like python, perl, javascript etc. might get away with it but compiled languages have to transform it in its code representation.These languages also don't store "interpolated strings" in variables; they store strings in variables, and any string interpolation happens at the literal. Crystal (compiled language with a real type system, etc.): apple = 0 apple = 36 puts my_is Ruby (interpreted scripting language): apple = 0 apple = 36 puts my_is Both output "apple=0". I can't recall a case where you'd get "apple=36". You'd have to deliberately delay evaluation of the literal. But I don't think anyone's asked for any other behavior than this. What's wanted is for int apple; string my_is = i"apple=$apple"; apple = 36; writeln(my_is); to output "apple=36" rather than result in a compile-time error because i"..." doesn't evaluate to a string.
Dec 17 2019
On Tuesday, 17 December 2019 at 17:31:20 UTC, mipri wrote:What's wanted is for int apple; string my_is = i"apple=$apple"; apple = 36; writeln(my_is); to output "apple=36"Of course this should read "apple=0". This is a mistake I wouldn't've made with a logical programming language :(
Dec 17 2019
On 12/17/19 5:14 AM, Patrick Schluter wrote:Yes, and that was the point of the exercice. Transforming the interpolated "string" into a string evaluates the values of the variables at the moment of that transformation. From then on, there is no interpolation possible as it a simple string. I suppose that what aliak leant in his comments was that the string then could still be used for interpolation. hypothetic scenario of what I interpreted what aliak wanted (and it won't compile, it's just for illustration) int apple; .... string my_is = i"apple=${apple}"; .... apple = 36; writeln(my_is); would print "apple=36" with this DIP, when you do this int apple; .... string my_is = i"apple=${apple}".format; .... apple = 36; writeln(my_is); will print "apple=0" because my_is will contain the string "apple=0" The basic thing here is what Walter said above: interpolated strings are not string literals, they can't be. They are code.Wow, I don't think that the first item can be done with the DIP. But that would be really cool (I'm thinking of periodic logging features). I tried this, still prints 5 apples and 6 bananas: int apples = 5; int bananas = 6; auto as = AliasSeq!("%s apples and %s bananas", apples, bananas); // essentially what an interpolated string will evaluate to writefln(as); ++apples; ++bananas; writefln(as); It seems that AliasSeq doesn't store the alias (ironically), but the value of the expression at the time. Is there a way that this could work? I mean, aside from storing lambdas for everything? -Steve
Dec 17 2019
On 17.12.19 18:12, Steven Schveighoffer wrote:I tried this, still prints 5 apples and 6 bananas: int apples = 5; int bananas = 6; auto as = AliasSeq!("%s apples and %s bananas", apples, bananas); // essentially what an interpolated string will evaluate to writefln(as); ++apples; ++bananas; writefln(as); It seems that AliasSeq doesn't store the alias (ironically), but the value of the expression at the time. Is there a way that this could work? I mean, aside from storing lambdas for everything?alias as = AliasSeq!("%s apples and %s bananas", apples, bananas);
Dec 17 2019
On 12/17/19 12:19 PM, ag0aep6g wrote:On 17.12.19 18:12, Steven Schveighoffer wrote::facepalm: Thanks! That is pretty cool. Coupled with a logging function: import std.experimental.logger; int apples = 5; int bananas = 6; //equivalent to: alias msg = i"$apples apples and $bananas bananas"; alias msg = AliasSeq!("%s apples and %s bananas", apples, bananas); logf(msg); ++apples; ++bananas; logf(msg); This works pretty well, shows the filename/line numbers, and reevaluates the log message each time. Another cool use case. -SteveIs there a way that this could work? I mean, aside from storing lambdas for everything?alias as = AliasSeq!("%s apples and %s bananas", apples, bananas);
Dec 17 2019
On Tuesday, 17 December 2019 at 17:31:05 UTC, Steven Schveighoffer wrote:On 12/17/19 12:19 PM, ag0aep6g wrote:This got me excited, but unfortunately it doesn't work with expressions (for obvious reasons): // Error: variable apples cannot be read at compile time alias msg = AliasSeq!("%s apples and %s bananas makes %s fruit", apples, bananas, apples + bananas);On 17.12.19 18:12, Steven Schveighoffer wrote::facepalm: Thanks! That is pretty cool. Coupled with a logging function: import std.experimental.logger; int apples = 5; int bananas = 6; //equivalent to: alias msg = i"$apples apples and $bananas bananas"; alias msg = AliasSeq!("%s apples and %s bananas", apples, bananas); logf(msg); ++apples; ++bananas; logf(msg); This works pretty well, shows the filename/line numbers, and reevaluates the log message each time. Another cool use case. -SteveIs there a way that this could work? I mean, aside from storing lambdas for everything?alias as = AliasSeq!("%s apples and %s bananas", apples, bananas);
Dec 17 2019
On 12/17/19 1:17 PM, Meta wrote:On Tuesday, 17 December 2019 at 17:31:05 UTC, Steven Schveighoffer wrote:Right, the alias has to be a symbol or a constant. Though you could technically put in a lambda. I don't know if the log/writef would support that. This doesn't mean it's not useful if it can only be a symbol, I predict even without string interpolation, my printf debugging that I generally use is going to be enhanced with this idea. -SteveThis works pretty well, shows the filename/line numbers, and reevaluates the log message each time. Another cool use case.This got me excited, but unfortunately it doesn't work with expressions (for obvious reasons): // Error: variable apples cannot be read at compile time alias msg = AliasSeq!("%s apples and %s bananas makes %s fruit", apples, bananas, apples + bananas);
Dec 17 2019
On Tuesday, 17 December 2019 at 18:17:30 UTC, Meta wrote:This got me excited, but unfortunately it doesn't work with expressions (for obvious reasons): // Error: variable apples cannot be read at compile time alias msg = AliasSeq!("%s apples and %s bananas makes %s fruit", apples, bananas, apples + bananas);tuple of lazy args should work probably (i.e. pass through vararg function that has all args marked as lazy. Best regards, Alexandru.
Dec 17 2019
On Tuesday, 17 December 2019 at 10:14:35 UTC, Patrick Schluter wrote:On Tuesday, 17 December 2019 at 09:20:06 UTC, Jacob Carlborg wrote:I'm pretty sure I said that I expect interpolated strings to be assignable to strings and that this DIP doesn't enable that. And people will need to understand tuples to understand what's happening. I'm not sure how you interpreted all the rest?[...]Yes, and that was the point of the exercice. Transforming the interpolated "string" into a string evaluates the values of the variables at the moment of that transformation. From then on, there is no interpolation possible as it a simple string. I suppose that what aliak leant in his comments was that the string then could still be used for interpolation. [...]
Dec 17 2019
On Tuesday, 17 December 2019 at 22:14:32 UTC, aliak wrote:On Tuesday, 17 December 2019 at 10:14:35 UTC, Patrick Schluter wrote:The question is, what is that string supposed to contain. The resolved interpolation ("apple = 0") or the interpolation string ("apple = $(apple)").On Tuesday, 17 December 2019 at 09:20:06 UTC, Jacob Carlborg wrote:I'm pretty sure I said that I expect interpolated strings to be assignable to strings and that this DIP doesn't enable that. And people will need to understand tuples to understand what's happening. I'm not sure how you interpreted all the rest?[...]Yes, and that was the point of the exercice. Transforming the interpolated "string" into a string evaluates the values of the variables at the moment of that transformation. From then on, there is no interpolation possible as it a simple string. I suppose that what aliak leant in his comments was that the string then could still be used for interpolation. [...]
Dec 18 2019
On Monday, 16 December 2019 at 11:18:33 UTC, Patrick Schluter wrote:On Monday, 16 December 2019 at 11:08:00 UTC, Patrick Schluter wrote:Well there is a issue in javascript, interpolated string are evaluated once met in code by interpreter and are not somehow delayed at later stage as in your example. Here is a test case: ``` var c = 40 var s = `${a + b} ${c}` var a = 10 var b = 20 console.log(s) ``` The result is: Nan 40 Best regards, AlexandruOn Monday, 16 December 2019 at 10:48:51 UTC, aliak wrote:Maybe I'm wrong here, I haven't thought it through, but in first approach I think that's an essential point. As the string contains code, if evaluated at CT, the string must be split somehow in literal parts and code parts. Allowing the i-string to be handled as regular string implies that the splitting happens sometime between when it is declared and after it is used, which can happen after runtime. import fn; int b = 20; string inter = i"$(a+b)"; foreach(a; 1..10) fn(inter); --- module fn; void fn(string s) { writefln(s); } How would that work? In python or javascript there's no issue, a is a runtime symbol.Resolving interpolation at compile time is imho incompatiblewith handling them as regular strings.The question is then do we want CT or RT interpolated strings. RT interpolated strings can still be provided by a library.
Dec 17 2019
On Monday, 16 December 2019 at 11:08:00 UTC, Patrick Schluter wrote:On Monday, 16 December 2019 at 10:48:51 UTC, aliak wrote:Exactly. And then explain why. And what is that thing on the right. And why is string assignment not working on an interpolated _string_?[...]because string s = ("%s",var); is a syntax error.Even a beginning programmer can understand that an interpolated string cannot be a pure simple string as it contains symbols and expressions that are language construct not part of the string literal, i.e. that the compiler has to perform some transformations to substitute these language symbols into a value. Interpolated strings, in any language, are not string literals.In any language, they can be assigned to strings.Each language resolves this fact in different manners and at different times. Interpreted languages do it at runtime (obviously), java like languages chose to do it at runtime. In a language like D, which prefers resolving what is resolvable at compile time, it would be loathed if it interpolation was resolved at runtime (remember how long people were bitching about runtime only format strings?) Resolving interpolation at compile time is imho incompatible with handling them as regular strings. The question is then do we want CT or RT interpolated strings. RT interpolated strings can still be provided by a library.See Adam's previous posts on his approach.
Dec 16 2019
On Monday, 16 December 2019 at 11:38:34 UTC, aliak wrote:On Monday, 16 December 2019 at 11:08:00 UTC, Patrick Schluter wrote:Not true for some languages I checked string is not a string and has to be converted with .toString which is equivalent in calling .format in D. - Rust and Java do not have interpolated strings - Swift I don't know. Looks powerful but in a whole different difficulty level. all others are interpreters python, perl, ruby, bash, tcl, VB, PHP etc. for whom it is much easier as there is no distinction between CT and RT.On Monday, 16 December 2019 at 10:48:51 UTC, aliak wrote:Exactly. And then explain why. And what is that thing on the right. And why is string assignment not working on an interpolated _string_?[...]because string s = ("%s",var); is a syntax error.Even a beginning programmer can understand that an interpolated string cannot be a pure simple string as it contains symbols and expressions that are language construct not part of the string literal, i.e. that the compiler has to perform some transformations to substitute these language symbols into a value. Interpolated strings, in any language, are not string literals.In any language, they can be assigned to strings.// Use reduce to calculate the sum // of all squares in parallel. auto result = taskPool.reduce!"a+b"( 0.0, iota(100).map!"a*a"); writeln("Sum of squares: ", result);Each language resolves this fact in different manners and at different times. Interpreted languages do it at runtime (obviously), java like languages chose to do it at runtime. In a language like D, which prefers resolving what is resolvable at compile time, it would be loathed if it interpolation was resolved at runtime (remember how long people were bitching about runtime only format strings?) Resolving interpolation at compile time is imho incompatible with handling them as regular strings. The question is then do we want CT or RT interpolated strings. RT interpolated strings can still be provided by a library.See Adam's previous posts on his approach.
Dec 16 2019
On Monday, 16 December 2019 at 12:43:04 UTC, Patrick Schluter wrote:// Use reduce to calculate the sum // of all squares in parallel. auto result = taskPool.reduce!"a+b"( 0.0, iota(100).map!"a*a"); writeln("Sum of squares: ", result);Ignore that random crap at the end of my post. It was a copy paste accident.
Dec 16 2019
On Monday, 16 December 2019 at 12:43:04 UTC, Patrick Schluter wrote:On Monday, 16 December 2019 at 11:38:34 UTC, aliak wrote:You can assign strings to interpolated strings in all these languages you mentioned that have interpolated string support Kotlin: var x = 3 var s: String = "$x" + "$x" Swift: let x = 3 let y: String = "\(x)" string n = "hello"; string x = $"{n}";On Monday, 16 December 2019 at 11:08:00 UTC, Patrick Schluter wrote:Not true for some languages I checked interpolated string is not a string and has to be converted with .toString which is equivalent in calling .format in D. - Rust and Java do not have interpolated strings - Swift I don't know. Looks powerful but in a whole different difficulty level.[...]Exactly. And then explain why. And what is that thing on the right. And why is string assignment not working on an interpolated _string_?[...]In any language, they can be assigned to strings.
Dec 16 2019
On Monday, 16 December 2019 at 10:48:51 UTC, aliak wrote:On Monday, 16 December 2019 at 01:35:51 UTC, Walter Bright wrote:import std.format: format; string s = format(i"$var");On 12/15/2019 2:17 AM, Aliak wrote:User: why can't I do this?/Why doesn't this work? string s = i"$var"; Answer?To use it people will need to understand how to use d tuples as well.No, they don't.
Dec 16 2019
On Monday, 16 December 2019 at 13:22:45 UTC, Atila Neves wrote:On Monday, 16 December 2019 at 10:48:51 UTC, aliak wrote:That isn't an answer to the question, it's just a workaround. Interpolated strings could implicitly convert to strings, which is the most common use case in typical D code. That would not bloat code that doesn't need it, as Adam has shown by using an import inside a template. Interpolated strings should not be designed with low-level concerns as the priority motivator at the cost of high level usability and safety. D is supposed to be a type safe language, even std.format.format is not fully type safe because using string for a format string allows runtime errors. Any good D interpolation proposal would support compile time checked format strings, even when runtime arguments are passed. D is supposed to be the best language for compile time stuff!User: why can't I do this?/Why doesn't this work? string s = i"$var"; Answer?import std.format: format; string s = format(i"$var");
Dec 16 2019
On 12/16/2019 6:00 AM, Nick Treleaven wrote:On Monday, 16 December 2019 at 13:22:45 UTC, Atila Neves wrote:Having it go directly to a string has multiple problems: 1. Those who want the tuple in order to do something else with it will be unhappy and out of luck. 2. It will not work with betterC. 3. It will allocate GC memory. 4. It will be substantially slower because of the extra intermediate buffer. 5. I don't think it'll work with Steven Schweighoffer's SQL examples. 6. It will require the core language to depend on a rather large and complex Phobos routine. 7. It will not be any more typesafe than it would be generating a tuple. 8. The number of times I've wanted a formatted string as the end result, as opposed to wanting formatted insertion into something else, is about 1 in 100, if that.On Monday, 16 December 2019 at 10:48:51 UTC, aliak wrote:That isn't an answer to the question, it's just a workaround. Interpolated strings could implicitly convert to strings, which is the most common use case in typical D code. That would not bloat code that doesn't need it, as Adam has shown by using an import inside a template. Interpolated strings should not be designed with low-level concerns as the priority motivator at the cost of high level usability and safety. D is supposed to be a type safe language, even std.format.format is not fully type safe because using string for a format string allows runtime errors. Any good D interpolation proposal would support compile time checked format strings, even when runtime arguments are passed. D is supposed to be the best language for compile time stuff!User: why can't I do this?/Why doesn't this work? string s = i"$var"; Answer?import std.format: format; string s = format(i"$var");
Dec 16 2019
On Monday, 16 December 2019 at 21:42:32 UTC, Walter Bright wrote:Having it go directly to a string has multiple problems: 1. Those who want the tuple in order to do something else with it will be unhappy and out of luck. 2. It will not work with betterC. 3. It will allocate GC memory. 4. It will be substantially slower because of the extra intermediate buffer. 5. I don't think it'll work with Steven Schweighoffer's SQL examples. 6. It will require the core language to depend on a rather large and complex Phobos routine. 7. It will not be any more typesafe than it would be generating a tuple. 8. The number of times I've wanted a formatted string as the end result, as opposed to wanting formatted insertion into something else, is about 1 in 100, if that.It doesn't need to go directly to a string. Just the end result needs to be a string. In Swift they achieve this by lowering the string interpolation to a set of method calls: "The time is \(time)." Is lowered to something like: var interpolation = MyString.StringInterpolation(literalCapacity: 13, interpolationCount: 1) interpolation.appendLiteral("The time is ") interpolation.appendInterpolation(time) interpolation.appendLiteral(".") MyString(stringInterpolation: interpolation) These methods are overridable to be able to customize the behavior. -- /Jacob Carlborg
Dec 17 2019
On Tuesday, 17 December 2019 at 08:55:36 UTC, Jacob Carlborg wrote:It doesn't need to go directly to a string. Just the end result needs to be a string. In Swift they achieve this by lowering the string interpolation to a set of method calls: "The time is \(time)." Is lowered to something like: var interpolation = MyString.StringInterpolation(literalCapacity: 13, interpolationCount: 1) interpolation.appendLiteral("The time is ") interpolation.appendInterpolation(time) interpolation.appendLiteral(".") MyString(stringInterpolation: interpolation) These methods are overridable to be able to customize the behavior.With this implementation SwiftUI supports internationalization of string literals with interpolation. -- /Jacob Carlborg
Dec 17 2019
On Monday, 16 December 2019 at 21:42:32 UTC, Walter Bright wrote:On 12/16/2019 6:00 AM, Nick Treleaven wrote:I said implicitly convert. If it lowers to a templated struct, it can still be used without converting to string - see below.Interpolated strings could implicitly convert to strings, which is the most common use case in typical D code. That would not bloat code that doesn't need it, as Adam has shown by using an import inside a template. Interpolated strings should not be designed with low-level concerns as the priority motivator at the cost of high level usability and safety. D is supposed to be a type safe language, even std.format.format is not fully type safe because using string for a format string allows runtime errors. Any good D interpolation proposal would support compile time checked format strings, even when runtime arguments are passed. D is supposed to be the best language for compile time stuff!Having it go directly to a string has multiple problems:1. Those who want the tuple in order to do something else with it will be unhappy and out of luck.struct FormatSeq(S...) { /// the sequence for e.g. printf S expand; alias get this; property string get()() // template, doesn't link Phobos unless needed { import std.format; return format(expand); } } unittest { int i = 5; string s = "hi"; //auto fs = i"$i, $s"; auto fs = FormatSeq!(string, int, string)("%s, %s", i, s); //lowering import std.stdio; writefln(fs.expand); // works as format string string s2 = fs; // works as string implicitly too s2.writeln; }2. It will not work with betterC. 3. It will allocate GC memory. 4. It will be substantially slower because of the extra intermediate buffer.None of these points are true, just use `.expand` and avoid the alias this.5. I don't think it'll work with Steven Schweighoffer's SQL examples.The above get method would do the wrong thing, yes. Perhaps if the format string is a struct template value parameter, the code can detect that custom specifiers have been used and statically disable the get method.6. It will require the core language to depend on a rather large and complex Phobos routine.Only if the alias this is actually used - it's a template. The precedent for lowering to Phobos is the ^^ operator which IIRC lowers to std.math.pow.7. It will not be any more typesafe than it would be generating a tuple.The common case for creating a string is seamless and can't be done wrong when using alias this, which is also the easiest way to use it. printf could be wrapped with a method, and the format string could be checked at compile-time when it's a literal.8. The number of times I've wanted a formatted string as the end result, as opposed to wanting formatted insertion into something else, is about 1 in 100, if that.So just put .expand after the interpolated string. For *every* programming language I'm aware of, interpolated strings implicitly convert to a string. If it really is as commonly needed as you think, you can add wrapper methods to the struct so you even avoid importing core.stdc or std.stdio.
Dec 17 2019
On Monday, 16 December 2019 at 13:22:45 UTC, Atila Neves wrote:On Monday, 16 December 2019 at 10:48:51 UTC, aliak wrote:This is non obvious. And only explainable by mentioning tuples.On Monday, 16 December 2019 at 01:35:51 UTC, Walter Bright wrote:import std.format: format; string s = format(i"$var");On 12/15/2019 2:17 AM, Aliak wrote:User: why can't I do this?/Why doesn't this work? string s = i"$var"; Answer?To use it people will need to understand how to use d tuples as well.No, they don't.
Dec 16 2019
On Monday, 16 December 2019 at 14:02:17 UTC, aliak wrote:On Monday, 16 December 2019 at 13:22:45 UTC, Atila Neves wrote:In other words. You didn't answer anything. You just told the user what to do with no explanation as to why that has to be done.On Monday, 16 December 2019 at 10:48:51 UTC, aliak wrote:This is non obvious. And only explainable by mentioning tuples.On Monday, 16 December 2019 at 01:35:51 UTC, Walter Bright wrote:import std.format: format; string s = format(i"$var");On 12/15/2019 2:17 AM, Aliak wrote:User: why can't I do this?/Why doesn't this work? string s = i"$var"; Answer?To use it people will need to understand how to use d tuples as well.No, they don't.
Dec 16 2019
On Monday, 16 December 2019 at 14:02:17 UTC, aliak wrote:On Monday, 16 December 2019 at 13:22:45 UTC, Atila Neves wrote:It's worse than non-obvious: it's contrary to expectation. It's something that docs are going to have to explain and justify. It's something that people are going to want the compiler to special case if only for a useful error message. And you get the same problem in void greet(string name) { writeln("Hello, ", name); } void main(string[] args) { string title = "Mr."; greet(i"$title $(args[1])"); } Error: function myfirstdprogram.greet(string name) is not callable using argument types (string, string, string) // But I'm never calling greet with three strings? Why is it // saying the error is on a line with only one string? It is, however, not that hard to explain and justify. That it works for assigning the parameters is a little weird. That it works for SQL is pretty cool. That it works for translation is, actually, a very worthwhile innovation and a good reason to keep the proposed behavior even if it's weird. And 'tuples' in this sense do come up in other languages: https://stackoverflow.com/questions/2322355/proper-name-for-python-operator In terms of "reasons people get confused or doubtful and wander away from D" I don't think it'll come anywhere close to someone trying to make std.range and std.algorithm work while not having a great understanding of how they're implemented or why. Still, some way to at least auto-import and auto-use format() would be nice (if adding to -betterC caveats). If functions accepting a printf-style string just had a different type, extern(C) snprintf(scope char* s, size_t n, scope const ichar* format, ...); then format() could be auto-invoked in string-typed i"" and you get the benefits without the immediate blow to new users. Of course then you have to justify all the different char types, including combinations, whether idchar vs. dichar is the valid one. It's gross, so I can understand why it's already been mentioned and discarded as an option in the thread, but it just seems inevitable that if DIP 1027 is added without some kind of hack like this, that one will get added on later anyway, after people keep complaining that D's interpolation is wrong or weird.On Monday, 16 December 2019 at 10:48:51 UTC, aliak wrote:This is non obvious. And only explainable by mentioning tuples.On Monday, 16 December 2019 at 01:35:51 UTC, Walter Bright wrote:import std.format: format; string s = format(i"$var");On 12/15/2019 2:17 AM, Aliak wrote:User: why can't I do this?/Why doesn't this work? string s = i"$var"; Answer?To use it people will need to understand how to use d tuples as well.No, they don't.
Dec 16 2019
On Sunday, 15 December 2019 at 04:20:59 UTC, Walter Bright wrote:object.d is getting more and more bloated over time. This is not a solution to imports, and is not a good trend.A bit other topic, but this can be fixed by splitting object.d in multiple modules in same package, and auto import that package, just like how it is done in java with java.lang package. For example, object.d could be split into several modules under d.lang package. This will also clean existing bloatware, since we could move typeinfo, object definition and other stuff into separated modules. Best regards, Alexandru.
Dec 15 2019
On 15/12/2019 11:33 PM, Alexandru Ermicioi wrote:On Sunday, 15 December 2019 at 04:20:59 UTC, Walter Bright wrote:Yes please.object.d is getting more and more bloated over time. This is not a solution to imports, and is not a good trend.A bit other topic, but this can be fixed by splitting object.d in multiple modules in same package, and auto import that package, just like how it is done in java with java.lang package. For example, object.d could be split into several modules under d.lang package. This will also clean existing bloatware, since we could move typeinfo, object definition and other stuff into separated modules. Best regards, Alexandru.
Dec 15 2019
On 12/15/2019 2:33 AM, Alexandru Ermicioi wrote:On Sunday, 15 December 2019 at 04:20:59 UTC, Walter Bright wrote:The reality is that compilation time is more proportional to the number of files than the size of the files. Splitting up object.d into multiple modules that must still be loaded will make things slower. Also, splitting it up into multiple modules does not eliminate the complexity of it.object.d is getting more and more bloated over time. This is not a solution to imports, and is not a good trend.A bit other topic, but this can be fixed by splitting object.d in multiple modules in same package, and auto import that package, just like how it is done in java with java.lang package. For example, object.d could be split into several modules under d.lang package. This will also clean existing bloatware, since we could move typeinfo, object definition and other stuff into separated modules.
Dec 16 2019
On Monday, 16 December 2019 at 09:34:00 UTC, Walter Bright wrote:On 12/15/2019 2:33 AM, Alexandru Ermicioi wrote:I doubt someone will complain, about splitting object module into smaller packages based on performance reasons, and certainly splitting object.d won't trigger tens of files now. Though as said before it will increase readability. I personally can live with few more miliseconds for compilation time if readability is increased in druntime/phobos. Best regards, Alexandru.On Sunday, 15 December 2019 at 04:20:59 UTC, Walter Bright wrote:The reality is that compilation time is more proportional to the number of files than the size of the files. Splitting up object.d into multiple modules that must still be loaded will make things slower.object.d is getting more and more bloated over time. This is not a solution to imports, and is not a good trend.A bit other topic, but this can be fixed by splitting object.d in multiple modules in same package, and auto import that package, just like how it is done in java with java.lang package. For example, object.d could be split into several modules under d.lang package. This will also clean existing bloatware, since we could move typeinfo, object definition and other stuff into separated modules.
Dec 17 2019
On 12/17/2019 6:19 AM, Alexandru Ermicioi wrote:I doubt someone will complain, about splitting object module into smaller packages based on performance reasons, and certainly splitting object.d won't trigger tens of files now. Though as said before it will increase readability. I personally can live with few more miliseconds for compilation time if readability is increased in druntime/phobos.People often complain as DMD's compile speed steadily deteriorates. A few more milliseconds at a time add up.
Dec 20 2019
On Sunday, 15 December 2019 at 01:52:20 UTC, Adam D. Ruppe wrote:string a = i"";This is for me the most important thing for string interpolation. A convenient string assignment. If this is not convenient, it destroys the great feature of string interpolation. Walter, could you please make it happen? Kind regards Andre
Dec 15 2019
On Sunday, 15 December 2019 at 09:30:45 UTC, Andre Pany wrote:Careful that if that happens, then it may be another feature that can't be used without a runtime. As it stands, it is usable with snprintf nogc and that's pretty cool in my book.string a = i"";This is for me the most important thing for string interpolation. A convenient string assignment. If this is not convenient, it destroys the great feature of string interpolation. Walter, could you please make it happen? Kind regards Andre
Dec 15 2019
On Sunday, 15 December 2019 at 15:36:09 UTC, Guillaume Piolat wrote:On Sunday, 15 December 2019 at 09:30:45 UTC, Andre Pany wrote:There's no reason it can't be implicitly converted to a string. You could also easily write a nogc wrapper if it outputs a tuple. It being usable with snprintf() means it outputs something that pretty much no other function uses. The only thing I know of that implements printf-style formatting is printf (or uses sprintf to implement it). All other use cases (the more common ones) this becomes a useless feature. Ultimately this DIP is trying to push a library specific detail (from another language) into D. That's just a bad idea.Careful that if that happens, then it may be another feature that can't be used without a runtime. As it stands, it is usable with snprintf nogc and that's pretty cool in my book.string a = i"";This is for me the most important thing for string interpolation. A convenient string assignment. If this is not convenient, it destroys the great feature of string interpolation. Walter, could you please make it happen? Kind regards Andre
Dec 15 2019
On Sunday, 15 December 2019 at 17:26:57 UTC, Jab wrote:It being usable with snprintf() means it outputs something that pretty much no other function uses.D's writef uses it too, as well as std.format. Do do the vibe logging functions. It is a common format. (though D's writef is supposed to replace C's printf... for great part because of type safety.))
Dec 15 2019
On Sunday, 15 December 2019 at 17:38:29 UTC, Adam D. Ruppe wrote:On Sunday, 15 December 2019 at 17:26:57 UTC, Jab wrote:Which brings this to mind: import std.stdio; void main() { int n, m; write("input: "); readf(i"$n - $m"); writeln(n + m); } As used: $ ./test input: 2 - 8 10 When's the last time you saw string interpolation that resulted in the variables getting set to new values?It being usable with snprintf() means it outputs something that pretty much no other function uses.D's writef uses it too, as well as std.format. Do do the vibe logging functions. It is a common format.
Dec 15 2019
On Sunday, 15 December 2019 at 17:50:56 UTC, mipri wrote:When's the last time you saw string interpolation that resulted in the variables getting set to new values?I actually think that is a cool feature of the proposal. (though i hate readf, the general idea of populating placeholders is a nice one)
Dec 15 2019
On 12/15/2019 10:03 AM, Adam D. Ruppe wrote:I actually think that is a cool feature of the proposal. (though i hate readf, the general idea of populating placeholders is a nice one)It works with scanf, too, though I never use scanf.
Dec 15 2019
On Sunday, 15 December 2019 at 17:38:29 UTC, Adam D. Ruppe wrote:On Sunday, 15 December 2019 at 17:26:57 UTC, Jab wrote:Literally the next sentence:It being usable with snprintf() means it outputs something that pretty much no other function uses.D's writef uses it too, as well as std.format. Do do the vibe logging functions. It is a common format. (though D's writef is supposed to replace C's printf... for great part because of type safety.))The only thing I know of that implements printf-style formatting is printf (or uses sprintf to implement it).This is going to add a feature to the language that is dependent on a library feature. Even though the compiler creates and verifies the format strings, it's going to have to re-parse the format string at runtime anyways. Implementing string interpolation will just grow the dependency on printf/sprintf. Cause like I said, no other function really actually implements that formatting scheme themselves. This limits and over-complicates the code around it.
Dec 15 2019
On Sunday, 15 December 2019 at 20:07:23 UTC, Jab wrote:Literally the next sentence:writef is neither printf nor does it use sprintf to implement it (except for floating point types... much to the chagrin of would-be CTFE users). D embraced printf's format and re-implemented it a long time ago.
Dec 15 2019
On Sunday, 15 December 2019 at 20:15:38 UTC, Adam D. Ruppe wrote:for floating point typesExactly.
Dec 15 2019
On Sunday, 15 December 2019 at 17:26:57 UTC, Jab wrote:On Sunday, 15 December 2019 at 15:36:09 UTC, Guillaume Piolat There's no reason it can't be implicitly converted to a string.Okay. Let's say this would compile: int stuff = 4; string s = i"my interpolated %stuff string"; Where should the result of i"my interpolated %stuff string" be allocated? If you answer "with the GC", then this feature requires the runtime...
Dec 15 2019
On Sunday, 15 December 2019 at 18:25:40 UTC, Guillaume Piolat wrote:On Sunday, 15 December 2019 at 17:26:57 UTC, Jab wrote:"Implicitly converted" meaning it exists as something else and can be converted to it. If you don't want the GC then don't use a string. nogc: int stuff = 4; auto t = i"my interpolated %stuff string"; string s = mallocString(t); // no different than having to call malloc() + snprintf()On Sunday, 15 December 2019 at 15:36:09 UTC, Guillaume Piolat There's no reason it can't be implicitly converted to a string.Okay. Let's say this would compile: int stuff = 4; string s = i"my interpolated %stuff string"; Where should the result of i"my interpolated %stuff string" be allocated? If you answer "with the GC", then this feature requires the runtime...
Dec 15 2019
On Sunday, 15 December 2019 at 18:25:40 UTC, Guillaume Piolat wrote:If you answer "with the GC", then this feature requires the runtime...That's exactly what mine would do. But at the same time, with mine, you could *also* do snprintf(buffer.ptr, buffer.length, i"foo %bar".c.tupleof); Check out a draft hacky 100% library implementation here: http://arsdnet.net/inter.d the compiler can do a slightly better job avoiding the copying of values (the library can too... but not if you also want all three: RT+CT compat, C function compat, and expressions in the interpolated string. It is a kinda pick any two. Unless I'm missing a cool trick. But the compiler can express more than the library.)
Dec 15 2019
On Sunday, 15 December 2019 at 20:32:38 UTC, Adam D. Ruppe wrote:On Sunday, 15 December 2019 at 18:25:40 UTC, Guillaume Piolat wrote:On second thought, it's true interpolated string are most wanted _when generating website pages_ and it's not like we would miss it that much in -betterC / or with disabled runtime.If you answer "with the GC", then this feature requires the runtime...That's exactly what mine would do.
Dec 15 2019
On Sunday, 15 December 2019 at 01:44:18 UTC, Walter Bright wrote:On 12/14/2019 6:23 AM, Adam D. Ruppe wrote:I highly doubt that modern D applications use printf enough that we should cater so much for it. Anyhow, I don't see why we couldn't add an overload even for printf in druntime if the .toString or .asFormatTuple is too much syntax.On Saturday, 14 December 2019 at 09:10:47 UTC, Walter Bright wrote:I was afraid that would be it. The extra syntax kills it,I find your proposal a little confusing. By turning the string into an object, it doesn't work with printf?Right, not directly. But then it is trivial to add a member of the object that transforms it into a tuple suitable for printf. So the end user's code now looks like: `printf(i"foo %bar".asFormatTuple);`along with the extra import required,It's a member of the struct. No import required.along with not working with #betterC.Why? I don't see an argument for this. The interpolated struct is templated, so the compiler would generate a new instance properly. In fact, even a potential printf overload in druntime would still work with #worseD as long as its templated.
Dec 15 2019
On 12/11/2019 11:30 PM, mipri wrote:void takes_a_normal_string(string s) { } takes_a_normal_string(i"%one + %two = %(one + two).");I'm not sure what you expect that to do?
Dec 13 2019
On Friday, 13 December 2019 at 08:54:08 UTC, Walter Bright wrote:On 12/11/2019 11:30 PM, mipri wrote:Complete example: import std.stdio; void takes_a_normal_string(string s) { writeln(s); } void main() { immutable one = 1, two = 2; takes_a_normal_string(i"%one + %two = %(one + two)."); } Output: 1 + 2 = 3 But, this works with DIP 1027, so I think it's fine: import std.format; ... takes_a_normal_string(i"%one + %two = %(one + two).".format);void takes_a_normal_string(string s) { } takes_a_normal_string(i"%one + %two = %(one + two).");I'm not sure what you expect that to do?
Dec 13 2019
On Wednesday, 11 December 2019 at 09:52:21 UTC, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1027, "String Interpolation": https://github.com/dlang/DIPs/blob/148001a963f5d6e090bb6beef5caf9854372d0bc/DIPs/DIP1027.md All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on December 25, or when I make a post declaring it complete. At the end of Round 1, if further review is deemed necessary, the DIP will be scheduled for another round of Community Review. Otherwise, it will be queued for the Final Review and Formal Assessment. Anyone intending to post feedback in this thread is expected to be familiar with the reviewer guidelines: https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md *Please stay on topic!* Thanks in advance to all who participate.1. The DIP fails to mention why this has been chosen as better over the other alternatives out there. 2. Why %? a) it clashes with format specifiers, sounds like a bad idea. b) it's more common in text than other alternatives (e.g. $) which means it increases making the user escape text. 3. How does this work with normal strings? And token strings? One use-case I've been looking forward to is generative programming with token strings and interpolated strings. This doesn't seem to help there? If not, why a half solution? If it does, then maybe an example? 4. How is this handled? auto d = 7; writefln(i"I ate %apples and %{d}bananas totalling %(apples + bananas) fruit."); // bug? silent failure? compiler error? Does it do what the user expects? 5. I believe you can do everything this DIP does with a better syntax -> "$itemPrice%.2f" where $ is the identifier and after the % is the formatting. And you don't have to deal with that * runtime error 6. What's the rationale behind allowing anything other than %s? The type of variable can be inferred? Cheers, - Ali
Dec 11 2019
On Wednesday, 11 December 2019 at 09:52:21 UTC, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1027, "String Interpolation": https://github.com/dlang/DIPs/blob/148001a963f5d6e090bb6beef5caf9854372d0bc/DIPs/DIP1027.md All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on December 25, or when I make a post declaring it complete. At the end of Round 1, if further review is deemed necessary, the DIP will be scheduled for another round of Community Review. Otherwise, it will be queued for the Final Review and Formal Assessment. Anyone intending to post feedback in this thread is expected to be familiar with the reviewer guidelines: https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md *Please stay on topic!* Thanks in advance to all who participate.Lowering interpolated strings to a format string and a tuple of values rather than just a tuple is less versatile than other solutions that have previously been proposed. This DIP pigeon-holes interpolated strings for one use case. Interpolated strings can be used for more than just creating strings. They are just a pretty syntax to interleave string literals and expressions. This solution is assuming the user will only use this for string formatting, but that's not necessarily the case. My original proposal lowered it directly to a tuple of string literals and expressions (https://github.com/dlang/dmd/pull/7988) and Adam Ruppe's proposal (http://dpldocs.info/this-week-in-d/Blog.Posted_2019_05_13.html) lowered it to a custom type where the same tuple could be accessed via a field. These solutions provide more versatility and are just as easy to print and format into strings with a single function call. Adam Ruppe's proposal was more complex than my own but improved versatility (i.e. added a method to convert it to a string without importing a module, allowed functions to overload on interpoated strings, provided access to the original raw un-interpolated string, etc). The problem with this DIP is that it's both more complex than my original proposal and less versatile. The other problem with this DIP is how it handles consecutive interpolated strings. Consider a case where you'd like to write a message with consecutive interpolated strings (see real life example here https://github.com/dlang/dmd/pull/7988/files#diff-685230fdddcb87fcbb4a344b264a2fb6L736): // using this DIP writefln(i" ... %a ... ", i" ... %b ... "); // becomes writefln(" ... %s ... ", a, " ... %s ... ", b); // that doesn't work, so you'd have to do this writeln(i" ... $(a) ... ".format, i" ... $(b) ... ".format); // by lowering to a tuple, you would get this writeln(i" ... %a ... ", i" ... %b ... "); // becomes writeln(" ... ", a, " ... ", " ... ", b, " .. "); I also don't see any mention of my proposal in the DIP in "Prior Work" or how this DIP compares to my proposal or Adam's.
Dec 11 2019
On Thursday, 12 December 2019 at 05:07:44 UTC, Jonathan Marler wrote: [...]I also don't see any mention of my proposal in the DIP in "Prior Work" or how this DIP compares to my proposal or Adam's.I think this is really important, because ignoring their work in the DIP is not encouraging. We all try to get the best solution and in speaking in general the DIP is taking care of a really useful feature I am missing. When I saw the first examples in vibe.d templates using ruby like
Dec 12 2019
On 12/12/19 12:07 AM, Jonathan Marler wrote:Lowering interpolated strings to a format string and a tuple of values rather than just a tuple is less versatile than other solutions that have previously been proposed. This DIP pigeon-holes interpolated strings for one use case. Interpolated strings can be used for more than just creating strings. They are just a pretty syntax to interleave string literals and expressions. This solution is assuming the user will only use this for string formatting, but that's not necessarily the case.Indeed, one can potentially have more use cases than format string plus tuple. That is one thing I don't like about it. But any technique we use to forward tuples and string formatting to a function is going to require adjustment in some cases, and work as-is in others. We did have problems with the straight tuple lowering (i.e. how do you tell which part was string literal and which parts were parameters). the new proposal handles that quite well in fact. Not to say that this isn't solvable, but I do like that aspect of the new DIP -- the string literal parts are clearly defined. It definitely needs changing from its current mechanism (the requirement of % for placeholder is too limiting IMO). One thing that might make things more useful -- if the compiler could define a new type istring, which is a derivative of string literal, and one could accept that as a parameter type for purposes of overloads if needed.My original proposal lowered it directly to a tuple of string literals and expressions (https://github.com/dlang/dmd/pull/7988) and Adam Ruppe's proposal (http://dpldocs.info/this-week-in-d/Blog.Posted_2019_05_13.html) lowered it to a custom type where the same tuple could be accessed via a field. These solutions provide more versatility and are just as easy to print and format into strings with a single function call. Adam Ruppe's proposal was more complex than my own but improved versatility (i.e. added a method to convert it to a string without importing a module, allowed functions to overload on interpoated strings, provided access to the original raw un-interpolated string, etc). The problem with this DIP is that it's both more complex than my original proposal and less versatile.I think all of them are somewhat equally versatile. With a mechanism to specify how to generate the format string, such as H. S. Toeh suggested, I think Walter's proposal is just as useful as yours or Adam's. All of them provide somewhat similar transformations, just the ordering of the string parts and the non-string parts are different. Unfortunately, I don't know if there's a way to forward the "tuple-ness" of the result by wrapping it if you needed to convert something. Even though Adam's proposal allows one to translate between what the compiler generates and what is needed, it copies the tuple into a type, which may not be what you want (e.g. Walter's example for apples, apples is an lvalue, but in Adam's it would always be an rvalue). There are limitations in yours as well, I like the ability to specify the formatting of the individual items, which would be difficult if not clunky in your proposal.The other problem with this DIP is how it handles consecutive interpolated strings. Consider a case where you'd like to write a message with consecutive interpolated strings (see real life example here https://github.com/dlang/dmd/pull/7988/files#diff-685230fdddcb87fcbb a344b264a2fb6L736): // using this DIP writefln(i" ... %a ... ", i" ... %b ... "); // becomes writefln(" ... %s ... ", a, " ... %s ... ", b); // that doesn't work, so you'd have to do this writeln(i" ... $(a) ... ".format, i" ... $(b) ... ".format);that does pose a slight problem, but one could potentially handle that with concatenation (i.e. concatenation of two interpolated strings results in the same thing as if you concatenated the two string literals and slapped i on the front).I also don't see any mention of my proposal in the DIP in "Prior Work" or how this DIP compares to my proposal or Adam's.This should be rectified. -Steve
Dec 12 2019
On 12/11/2019 9:07 PM, Jonathan Marler wrote:I also don't see any mention of my proposal in the DIP in "Prior Work"Indeed that is my fault and I'll fix that.
Dec 14 2019
On Wednesday, 11 December 2019 at 09:52:21 UTC, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1027, "String Interpolation":In my opinion, the semantics of string interpolation need to support: * The type of an interpolated string should be the same as a regular string. That means that the following should work: auto foo = 3; auto b = i"%foo"; static assert(is(typeof(b) == string)); * It should support both interpolating expressions and, with a shorter syntax, symbols, example: auto foo = 3; auto bar = 4; auto a = i"%foo" // interpolation of symbol auto b = i"%(foo + bar)" // interpolation of expression * It should not be tied to specific functions, like `printf` or `writef` * It needs to be possible to identify which part is a literal string and which part is an interpolation * A way to customize how the interpolation is performed. This I'm not sure how to do best. There are a couple of alternatives. In Swift string interpolation is lower to method calls [1]: "The time is \(time)." Is lowered to something like: var interpolation = MyString.StringInterpolation(literalCapacity: 13, interpolationCount: 1) interpolation.appendLiteral("The time is ") interpolation.appendInterpolation(time) interpolation.appendLiteral(".") MyString(stringInterpolation: interpolation) When it comes to the syntax. I think the existing suggestion to use `%` is bad, it's just going to cause conflicts with format specifiers for functions like `printf`. I would prefer to use the dollar sign, i.e. `$foo` and `$(a + b)`. [1] https://developer.apple.com/documentation/swift/stringinterpolationprotocol -- /Jacob Carlborg
Dec 13 2019
On 12/13/2019 5:11 AM, Jacob Carlborg wrote:* The type of an interpolated string should be the same as a regular string. That means that the following should work: auto foo = 3; auto b = i"%foo"; static assert(is(typeof(b) == string));That doesn't work because semantic analysis will convert it into a tuple.* It should support both interpolating expressions and, with a shorter syntax, symbols, example: auto foo = 3; auto bar = 4; auto a = i"%foo" // interpolation of symbol auto b = i"%(foo + bar)" // interpolation of expressionIt only makes sense if foo is an expression.* It should not be tied to specific functions, like `printf` or `writef`It works with anything that accepts a tuple.* It needs to be possible to identify which part is a literal string and which part is an interpolationI agree that is the whole point, and the proposal does that.* A way to customize how the interpolation is performed. This I'm not sure how to do best. There are a couple of alternatives. In Swift string interpolation is lower to method calls [1]: "The time is \(time)." Is lowered to something like: var interpolation = MyString.StringInterpolation(literalCapacity: 13, interpolationCount: 1) interpolation.appendLiteral("The time is ") interpolation.appendInterpolation(time) interpolation.appendLiteral(".") MyString(stringInterpolation: interpolation)The interpolation just creates a tuple. What the user does with the tuple is up to him.
Dec 14 2019
On 2019-12-14 10:21, Walter Bright wrote:That doesn't work because semantic analysis will convert it into a tuple.Yes, I understand that. I don't think it's a good idea. I wrote how I think it should work instead -- /Jacob Carlborg
Dec 14 2019
On Wednesday, 11 December 2019 at 09:52:21 UTC, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1027, "String Interpolation": https://github.com/dlang/DIPs/blob/148001a963f5d6e090bb6beef5caf9854372d0bc/DIPs/DIP1027.mdIf a special type is used for the format string after lowering, it can work with printf and other functions can use the format string at compile time: struct __Interpolate { immutable char *fmt; alias fmt this; } struct __InterpolateT(string fmt_) { enum fmt = fmt_; enum __Interpolate interpolate = __Interpolate(fmt_); alias interpolate this; } void main() { // printf can be used, because __InterpolateT converts to immutable(char)*: import core.stdc.stdio; printf(__InterpolateT!"test printf %d\n"(), 123); // Functions can detect an interpolated string using an overload: void writef(T...)(__Interpolate fmt, T params) { printf(fmt.fmt, params); } writef(__InterpolateT!"test writef %d\n"(), 123); // Functions can interpret the format string at compile time: void writefct(string fmt, T...)(__InterpolateT!fmt interpolate, T params) { pragma(msg, "format string at compile time ", fmt); printf(fmt, params); } writefct(__InterpolateT!"test writefct %d\n"(), 123); }
Dec 14 2019
On Wednesday, 11 December 2019 at 09:52:21 UTC, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1027, "String Interpolation": https://github.com/dlang/DIPs/blob/148001a963f5d6e090bb6beef5caf9854372d0bc/DIPs/DIP1027.mdI like this proposal. It sounds like a no-brainer YES.
Dec 15 2019
Some hashtags to get things started: #dip1027 #stringInterpolation
Dec 16 2019
On 12/11/19 4:52 AM, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1027, "String Interpolation": https://github.com/dlang/DIPs/blob/148001a963f5d6e090bb6beef5caf9854372 0bc/DIPs/DIP1027.md All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on December 25, or when I make a post declaring it complete. At the end of Round 1, if further review is deemed necessary, the DIP will be scheduled for another round of Community Review. Otherwise, it will be queued for the Final Review and Formal Assessment. Anyone intending to post feedback in this thread is expected to be familiar with the reviewer guidelines: https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md *Please stay on topic!* Thanks in advance to all who participate.Might I suggest we come up with a new name for this technique? I see there is going to be a lot of users who want true string interpolation, e.g.: string str = i"My name is $name"; and be very confused that D string interpolation isn't like https://en.wikipedia.org/wiki/String_interpolation Maybe something like "format tuple expansion" or "formatted interpolation"? -Steve
Dec 16 2019
On Monday, 16 December 2019 at 22:02:05 UTC, Steven Schveighoffer wrote:Might I suggest we come up with a new name for this technique? I see there is going to be a lot of users who want true string interpolation, e.g.: string str = i"My name is $name"; and be very confused that D string interpolation isn't like https://en.wikipedia.org/wiki/String_interpolation Maybe something like "format tuple expansion" or "formatted interpolation"? -SteveProgramming language terminology is so random already that this isn't going to help. Perl has 'hashes' and Python has 'dicts' and other languages have 'maps', but when I read about AAs in D I just said "oh, hash tables" and mentally translated all references from then on. People are going to do exactly the same thing to "tuple expansion strings" and still complain that "string interpolation in D" doesn't work as they expect. But if it's called "tuple expansion strings", they'll *also* complain about the weird name. There might be some satisfaction in saying "you *should* have expected something different because of the different name", or in giving an explanation of the different name, but this would all be a distraction from explaining why D's string interpolation is different.
Dec 16 2019
On Monday, 16 December 2019 at 22:12:37 UTC, mipri wrote:On Monday, 16 December 2019 at 22:02:05 UTC, Steven Schveighoffer wrote:The issue with user expectations should not be holding up on what to define for D. I checked today what other languages do and at consistent of what interpolated strings are. In rust it is even more than a joke as they call interpolated normal C style format string. So imo we should try to implement what fits the best the language and CT tuples is as D-ish as it gets.Might I suggest we come up with a new name for this technique? I see there is going to be a lot of users who want true string interpolation, e.g.: string str = i"My name is $name"; and be very confused that D string interpolation isn't like https://en.wikipedia.org/wiki/String_interpolation Maybe something like "format tuple expansion" or "formatted interpolation"? -SteveProgramming language terminology is so random already that this isn't going to help. Perl has 'hashes' and Python has 'dicts' and other languages have 'maps', but when I read about AAs in D I just said "oh, hash tables" and mentally translated all references from then on. People are going to do exactly the same thing to "tuple expansion strings" and still complain that "string interpolation in D" doesn't work as they expect. But if it's called "tuple expansion strings", they'll *also* complain about the weird name. There might be some satisfaction in saying "you *should* have expected something different because of the different name", or in giving an explanation of the different name, but this would all be a distraction from explaining why D's string interpolation is different.
Dec 16 2019
On Monday, 16 December 2019 at 22:33:57 UTC, Patrick Schluter wrote:what to define for D. I checked today what other languages do nothing consistent of what interpolated strings are.Not sure what you mean by this, I find popular languages to be remarkably consistent. Python: f"Three = {1 +2 }" $"Three = {1+2}" TypeScript: `Three = ${1 + 2}` Swift: "Three = \(1+2)"
Dec 16 2019
On Monday, 16 December 2019 at 22:12:37 UTC, mipri wrote:but this would all be a distraction from explaining why D's string interpolation is different.Here's some prose that I'd expect in a FAQ or tutorial. --- * What do you mean, "it doesn't build strings"!? i"$a $b $c" is translated to an argument list "%s %s %s", a, b, c So it has no meaning outside of argument-passing. * Why do that? No other language does that! Those other languages also have some severe problems owing to how they do string interpolation: 1. a universe of SQL injection and similar exploits, as it's easy and convenient to build strings with interpolation even though the underlying database APIs can accept arguments separately and safely, with no need for ad-hoc 'sanitization'. Well-written database code in these languages is therefore written as if string interpolation is not a feature of the language: $db->query("INSERT INTO names VALUES (?)", "Bob"); 2. internationalization is defeated, as the structure of the string that variables are interpolated into is lost. Invariably as programs get international their developers have to comb through the code base and remove uses of string interpolation: print("Hello, $name!"); printf(gettext("Hello, %s!"), name); where gettext() might look up "Hello, %s" in a translator-maintained table of greetings, to substitute "Bonjour, %s". In D, string interpolation is convenient for the simplest tasks, and D is unusual in that string interpolation *remains* convenient as tasks get more serious. This comes at the small cost of having to pass an interpolated string to a string-building function, like std.format's format, if that's what you want. string s1 = i"Hello, $name!"; // error string s2 = i"Hello, $name!".format; // this is fine string s3 = format("Hello, %s!", name); // without i"" --- Even if the intended purpose is working with C-style printf() functions, I'd highlight this use of i"" in a C interface or BetterC section.
Dec 16 2019
On Monday, 16 December 2019 at 22:48:30 UTC, mipri wrote:Those other languages also have some severe problems owing to how they do string interpolation: 1. a universe of SQL injection and similar exploits, as it's easy and convenient to build strings with interpolation even though the underlying database APIs can accept arguments separately and safely, with no need for ad-hoc 'sanitization'. Well-written database code in these languages is therefore written as if string interpolation is not a feature of the language: $db->query("INSERT INTO names VALUES (?)", "Bob");This would push the complexity onto the query implementation. As now it has to be able to parse the string.2. internationalization is defeated, as the structure of the string that variables are interpolated into is lost. Invariably as programs get international their developers have to comb through the code base and remove uses of string interpolation: print("Hello, $name!"); printf(gettext("Hello, %s!"), name);This would usually be a warning/error in C/C++ compilers as you aren't using a constant string for the format. It's a runtime variable and can't be checked by the compiler or at runtime so it's a security risk. D can do better due to varidic templates, but you are using printf and D doesn't have as robust warning/errors as some C/C++ compilers. Ultimately this doesn't really help with localization either. What if you need to change the order? Languages have different ways of formatting. Maybe not the best example, but say you have "$year-$month-$day", but in a different location it is more common to do "$month-$day-$year". The gettext() can't do anything about that, cause it'll always have to be "%d-%d-%d", it can't rearrange the order.where gettext() might look up "Hello, %s" in a translator-maintained table of greetings, to substitute "Bonjour, %s". In D, string interpolation is convenient for the simplest tasks, and D is unusual in that string interpolation *remains* convenient as tasks get more serious. This comes at the small cost of having to pass an interpolated string to a string-building function, like std.format's format, if that's what you want. string s1 = i"Hello, $name!"; // error string s2 = i"Hello, $name!".format; // this is fine string s3 = format("Hello, %s!", name); // without i"" --- Even if the intended purpose is working with C-style printf() functions, I'd highlight this use of i"" in a C interface or BetterC section.What happens if you want to implement your own type and pass it in? The DIP doesn't mention it at all. If you do what to do that it won't work with printf anymore. Unless you forcibly require some .toString() method for types that aren't supported. But even then that information about what type it was is then lost. It could have been passed with the type information and the caller could decide what to do with the extra information. Rather than requiring it to be forced into a string and potentially losing relevant information if it was otherwise passed to the function as a tuple.
Dec 16 2019
On Tuesday, 17 December 2019 at 05:37:53 UTC, Jab wrote:On Monday, 16 December 2019 at 22:48:30 UTC, mipri wrote:What? This is how query implementations work right now. Yes, the DBMS needs to be able to parse SQL. Have you spoken to a database without an ORM before?Well-written database code in these languages is therefore written as if string interpolation is not a feature of the language: $db->query("INSERT INTO names VALUES (?)", "Bob");This would push the complexity onto the query implementation. As now it has to be able to parse the string.https://www.gnu.org/software/libc/manual/html_node/Translation-with-gettext.htmlprintf(gettext("Hello, %s!"), name);This would usually be a warning/error in C/C++ compilers as you aren't using a constant string for the format.Ultimately this doesn't really help with localization either. What if you need to change the order? Languages have different ways of formatting. Maybe not the best example, but say you have "$year-$month-$day", but in a different location it is more common to do "$month-$day-$year". The gettext() can't do anything about that, cause it'll always have to be "%d-%d-%d", it can't rearrange the order."This doesn't help." is not supported by "I can think of a specific objection that internationalization libraries definitely have specific support for." OK, what about all the other cases? What if you format a date using a locale-aware formatter and then just make that one of the inputs to your format string, rather than the individual components of the date? It's still a better localization story than normal string interpolation, which just has to be ripped out. You can't fix normal string interpolation by using a locale-aware date formatter, because the resulting string is still not something you can look up in a translation database. Therefore, it helps despite this objection. Have you used gettext before?What happens if you want to implement your own type and pass it in? The DIP doesn't mention it at all.If you're passing the i"" string to a D routine like format() or writef(), then you get all the custom formatting that you want, as normal. If you're passing it to a C routine or something else, obviously you have to provide types that the C routine can understand. Have you printed a custom type in D before?
Dec 16 2019
On 12/16/2019 10:15 PM, mipri wrote:Have you printed a custom type in D before?Your response is well-written with good arguments, but please leave off the snark.
Dec 17 2019
On Tuesday, 17 December 2019 at 09:00:53 UTC, Walter Bright wrote:On 12/16/2019 10:15 PM, mipri wrote:Sure. I thought that was too much, as well.Have you printed a custom type in D before?Your response is well-written with good arguments, but please leave off the snark.
Dec 17 2019
On Tuesday, 17 December 2019 at 06:15:03 UTC, mipri wrote:On Tuesday, 17 December 2019 at 05:37:53 UTC, Jab wrote:Sorry I forgot to go back and edit this after I changed it. It be more complicated as instead of just using "?" it would have to be able to know about and parse printf-style formatting.On Monday, 16 December 2019 at 22:48:30 UTC, mipri wrote:What? This is how query implementations work right now. Yes, the DBMS needs to be able to parse SQL. Have you spoken to a database without an ORM before?Well-written database code in these languages is therefore written as if string interpolation is not a feature of the language: $db->query("INSERT INTO names VALUES (?)", "Bob");This would push the complexity onto the query implementation. As now it has to be able to parse the string.Ok? I've literally never seen this function used in any software. Probably for a good reason.https://www.gnu.org/software/libc/manual/html_node/Translation-with-gettext.htmlprintf(gettext("Hello, %s!"), name);This would usually be a warning/error in C/C++ compilers as you aren't using a constant string for the format.The date was just illustrating the problem. Sentence structures in languages change, the order isn't the same in every language. If your using printf, localization probably doesn't matter. Your going to have more problems with localization using printf. If localization matters, there's better methods for achieving it than using printf and something like gettext().Ultimately this doesn't really help with localization either. What if you need to change the order? Languages have different ways of formatting. Maybe not the best example, but say you have "$year-$month-$day", but in a different location it is more common to do "$month-$day-$year". The gettext() can't do anything about that, cause it'll always have to be "%d-%d-%d", it can't rearrange the order."This doesn't help." is not supported by "I can think of a specific objection that internationalization libraries definitely have specific support for." OK, what about all the other cases? What if you format a date using a locale-aware formatter and then just make that one of the inputs to your format string, rather than the individual components of the date? It's still a better localization story than normal string interpolation, which just has to be ripped out. You can't fix normal string interpolation by using a locale-aware date formatter, because the resulting string is still not something you can look up in a translation database.That's the problem. This is intended to be used for printf() as well, but to do that you have to do something like this then: printf(i"blah blah ${myType.toString.toStringz}"); It becomes useless here. You are going to have to use something else anyways because it starts to fall apart when you try and support an old method like printf.What happens if you want to implement your own type and pass it in? The DIP doesn't mention it at all.If you're passing the i"" string to a D routine like format() or writef(), then you get all the custom formatting that you want, as normal. If you're passing it to a C routine or something else, obviously you have to provide types that the C routine can understand.
Dec 17 2019
On Tue, Dec 17, 2019 at 05:37:53AM +0000, Jab via Digitalmars-d wrote:On Monday, 16 December 2019 at 22:48:30 UTC, mipri wrote:[...][...] The database engine *already* does this. It's standard SQL syntax, and you don't have to write a single bit of code to make this work, just hand it off to the database backend and your job is done. T -- "640K ought to be enough" -- Bill G. (allegedly), 1984. "The Internet is not a primary goal for PC usage" -- Bill G., 1995. "Linux has no impact on Microsoft's strategy" -- Bill G., 1999.$db->query("INSERT INTO names VALUES (?)", "Bob");This would push the complexity onto the query implementation. As now it has to be able to parse the string.
Dec 17 2019
On 12/16/2019 2:48 PM, mipri wrote:Here's some prose that I'd expect in a FAQ or tutorial. [...]Thank you, this is good stuff!
Dec 17 2019
On Monday, 16 December 2019 at 22:12:37 UTC, mipri wrote:Programming language terminology is so random already that this isn't going to help. Perl has 'hashes' and Python has 'dicts' and other languages have 'maps', but when I read about AAs in D I just said "oh, hash tables" and mentally translated all references from then on. People are going to do exactly the same thing to "tuple expansion strings" and still complain that "string interpolation in D" doesn't work as they expect.I think the name "associative array" is pretty good because I think it's the most generic name. "hash" or "hash table" has the indication that the implementation uses hashes. Funny thing, in Ruby it's called "hashes" as well, the class is even called "Hash". Prior to Ruby 1.9 it was implement has an actual hash table. In Ruby 1.9 they change the implementation to guarantee the order of the keys. That means that it cannot be implement as a hash table anymore. It still uses the name "Hash" though. -- /Jacob Carlborg
Dec 17 2019
On 12/11/19 4:52 AM, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1027, "String Interpolation": https://github.com/dlang/DIPs/blob/148001a963f5d6e090bb6beef5caf9854372 0bc/DIPs/DIP1027.md All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on December 25, or when I make a post declaring it complete. At the end of Round 1, if further review is deemed necessary, the DIP will be scheduled for another round of Community Review. Otherwise, it will be queued for the Final Review and Formal Assessment. Anyone intending to post feedback in this thread is expected to be familiar with the reviewer guidelines: https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md *Please stay on topic!* Thanks in advance to all who participate.BTW, people have been talking about usage like: auto str = i"I have $apples apples".format; And it got me thinking, does this actually work? I mean, can multiple parameters be used for UFCS? Answer: yes. auto str = AliasSeq!("I have %s apples", apples).format; // OK pretty cool. I had no idea. -Steve
Dec 17 2019
On Wednesday, 18 December 2019 at 01:20:33 UTC, Steven Schveighoffer wrote:On 12/11/19 4:52 AM, Mike Parker wrote:Huh. I wrote my example without UFCS precisely because I didn't know if that would work. Nice![...]BTW, people have been talking about usage like: auto str = i"I have $apples apples".format; And it got me thinking, does this actually work? I mean, can multiple parameters be used for UFCS? Answer: yes. auto str = AliasSeq!("I have %s apples", apples).format; // OK pretty cool. I had no idea.-Steve
Dec 18 2019
On Wednesday, 18 December 2019 at 01:20:33 UTC, Steven Schveighoffer wrote:[snip] BTW, people have been talking about usage like: auto str = i"I have $apples apples".format; And it got me thinking, does this actually work? I mean, can multiple parameters be used for UFCS? Answer: yes. auto str = AliasSeq!("I have %s apples", apples).format; // OK pretty cool. I had no idea. -SteveI think it works because format takes a variadic template as an input. Given the connection between variadic templates and AliasSeq, the input is basically an AliasSeq in the first place. Shouldn't be an issue having AliasSeq's with length>1. I don't know if I would describe it as multiple parameters. I would call UFCS with multiple parameters as describing when you have foo(x, y, z), you can call x.foo(y, z). In this case, something like auto str = AliasSeq!("I have %s apples").format(apples); also compiles without error and would be more comparable.
Dec 18 2019
On 12/18/19 9:18 AM, jmh530 wrote:On Wednesday, 18 December 2019 at 01:20:33 UTC, Steven Schveighoffer wrote:Nope. Not just variadic templates: assert(AliasSeq!(2, 2).pow == 4); Not even templates in general: int foo(int x, int y) { return x + y; } assert(AliasSeq!(1, 2).foo == 3); -Steve[snip] BTW, people have been talking about usage like: auto str = i"I have $apples apples".format; And it got me thinking, does this actually work? I mean, can multiple parameters be used for UFCS? Answer: yes. auto str = AliasSeq!("I have %s apples", apples).format; // OK pretty cool. I had no idea.I think it works because format takes a variadic template as an input. Given the connection between variadic templates and AliasSeq, the input is basically an AliasSeq in the first place. Shouldn't be an issue having AliasSeq's with length>1. I don't know if I would describe it as multiple parameters. I would call UFCS with multiple parameters as describing when you have foo(x, y, z), you can call x.foo(y, z). In this case, something like auto str = AliasSeq!("I have %s apples").format(apples); also compiles without error and would be more comparable.
Dec 18 2019
On Wednesday, 18 December 2019 at 17:41:42 UTC, Steven Schveighoffer wrote:[snip] Nope. Not just variadic templates: assert(AliasSeq!(2, 2).pow == 4); Not even templates in general: int foo(int x, int y) { return x + y; } assert(AliasSeq!(1, 2).foo == 3); -SteveInteresting.
Dec 18 2019
On Wednesday, 18 December 2019 at 22:02:59 UTC, jmh530 wrote:On Wednesday, 18 December 2019 at 17:41:42 UTC, Steven Schveighoffer wrote:Please keep comments in this thread focused on the DIP. I've got to read through the whole thread for the summary. OT posts don't help. I'm going to start deleting OT posts from this point forward. Thanks![snip] Nope. Not just variadic templates: assert(AliasSeq!(2, 2).pow == 4); Not even templates in general: int foo(int x, int y) { return x + y; } assert(AliasSeq!(1, 2).foo == 3); -SteveInteresting.
Dec 18 2019
On 12/18/19 5:24 PM, Mike Parker wrote:Please keep comments in this thread focused on the DIP. I've got to read through the whole thread for the summary. OT posts don't help. I'm going to start deleting OT posts from this point forward. Thanks!It's somewhat relevant because the usage case for tagging interpolated strings with .format requires this "feature", which I'm pretty sure was not intended. In fact, when I first thought of it, I came here to post that we may need a language change, only to find out it works fine! But sorry for the diversion. -Steve
Dec 18 2019
On Wednesday, 18 December 2019 at 22:24:05 UTC, Mike Parker wrote:Please keep comments in this thread focused on the DIP. I've got to read through the whole thread for the summary. OT posts don't help. I'm going to start deleting OT posts from this point forward.So here is a general response: 1. There is no unity on what to expect from interpolated strings in the thread. That suggests that a library solution should be established first using D meta programming capabilities. Only when there is unity behind a library solution (and it is being used in practice) should it be considered as a candidate for syntactic sugar in the compiler. 2. What is missing in terms of metaprogramming capabilities to do this well as a library solution. That ought to be addressed before making any extension to the compiler. 3. How does adding non-critical features to the compiler impact the ability to move forward with critical features such as improved non-gc memory management. What should the priority of this feature be related to other more imporant features? 4. How does this feature impact the learnability of the language. Currently it seams that newbies become confused by language features (not only in D, but also in Rust and C++), so how can D improve on that situation? And how can the design of this feature contribute positively in that regard?
Dec 20 2019
On Wednesday, 18 December 2019 at 17:41:42 UTC, Steven Schveighoffer wrote:On 12/18/19 9:18 AM, jmh530 wrote:I introduce you to a D library I was working on a couple of years back: https://gist.github.com/PetarKirov/a808c94857de84858accfb094c19bf77 ;)[...]Nope. Not just variadic templates: assert(AliasSeq!(2, 2).pow == 4); Not even templates in general: int foo(int x, int y) { return x + y; } assert(AliasSeq!(1, 2).foo == 3); -Steve
Dec 18 2019
On Wednesday, 11 December 2019 at 09:52:21 UTC, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1027, "String Interpolation": https://github.com/dlang/DIPs/blob/148001a963f5d6e090bb6beef5caf9854372d0bc/DIPs/DIP1027.mdHow are the following strings handled? i"hello $$name" // double $ i"hello $ name" // no following identifier i"hello $" // no following string i"hello \$name" // escaped $ i"hello $+name" // invalid following character (with the % -> $ change from a while back in the thread)
Dec 19 2019
On Wednesday, 11 December 2019 at 09:52:21 UTC, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1027, "String Interpolation": https://github.com/dlang/DIPs/blob/148001a963f5d6e090bb6beef5caf9854372d0bc/DIPs/DIP1027.md All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on December 25, or when I make a post declaring it complete. At the end of Round 1, if further review is deemed necessary, the DIP will be scheduled for another round of Community Review. Otherwise, it will be queued for the Final Review and Formal Assessment. Anyone intending to post feedback in this thread is expected to be familiar with the reviewer guidelines: https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md *Please stay on topic!* Thanks in advance to all who participate.. It also makes interpolated strings agnostic about what the format specifications are, as long as they start with %.Is there a reason it's not $ instead of %? String interpolation is most commonly use languages works like "my name is ${name}". Wouldn't it be easier if we target something users may already be familiar with?
Dec 26 2019
On Thursday, 26 December 2019 at 09:33:24 UTC, aberba wrote:On Wednesday, 11 December 2019 at 09:52:21 UTC, Mike Parker wrote:If you read in the thread, Walter accepted the change to $ because od %% problem I noticed in the beginning of the thread. I suppose he will amebd the document after that review cycle.[...][...]Is there a reason it's not $ instead of %? String interpolation is most commonly use languages works like "my name is ${name}". Wouldn't it be easier if we target something users may already be familiar with?
Dec 26 2019
On Thursday, 26 December 2019 at 10:20:06 UTC, Patrick Schluter wrote:If you read in the thread, Walter accepted the change to $ because od %% problem I noticed in the beginning of the thread. I suppose he will amebd the document after that review cycle.He updated it last week: https://github.com/dlang/DIPs/commit/1f5959abe482b1f9094f6484a7d0a3ade77fc2fc
Dec 26 2019
On Thursday, 26 December 2019 at 15:23:07 UTC, Mike Parker wrote:On Thursday, 26 December 2019 at 10:20:06 UTC, Patrick Schluter wrote:If you read in the thread, Walter accepted the change to $ because od %% problem I noticed in the beginning of the thread. I suppose he will amebd the document after that review cycle.He updated it last week: https://github.com/dlang/DIPs/commit/1f5959abe482b1f9094f6484a7d0a3ade77fc2fcNo attempt is made to diagnose format specification errors, such as attempting to formatan integer as a floating point value. The meaning of the format specifications is unknown to the core language. Why is this? If the language is going to embed the library feature of printf into the language spec, then it should know about and check formatting.string tool = "hammer"; writefln(i"hammering %s with $tool", "nails"); ``` will produce: ``` string tool = "hammer"; writefln("hammering %s with %s", tool, "nails"); ```There's an obvious problem, even with the given example. This will print: hammering hammer with nails Instead of the expected: hammering nails with hammer
Dec 26 2019
On Thursday, 26 December 2019 at 16:35:43 UTC, Jab wrote:Why is this? If the language is going to embed the library feature of printf into the language spec, then it should know about and check formatting.Please save further feedback for the next review round. This round is finished. I still need to work through the thread to summarize the feedback, so anything past this post will be ignored. Thanks!
Dec 26 2019