digitalmars.D - String interpolation, after a healthy debate on discord
- WebFreak001 (114/114) Dec 09 2021 We had an argument on the discord about the
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (9/14) Dec 09 2021 It is nice to see that you are thinking of ways to make this more
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (4/5) Dec 09 2021 Many ROADS…
- forkit (8/10) Dec 09 2021 I'd be happier if interpolated strings were removed completely.
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (8/11) Dec 09 2021 I understand your viewpoint, but imagine if you actually had a
- forkit (9/13) Dec 09 2021 My experience with such tooling, is that they create extra
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (7/10) Dec 10 2021 So you turn it off and request help by hitting ctrl-space instead?
- deadalnix (5/19) Dec 10 2021 This is much better. You'll note that the `i""` doesn't need to
- Ogi (4/8) Dec 10 2021 Not only that, you’ll have to import `std.cov` or `std.format`
- Adam D Ruppe (3/5) Dec 10 2021 This syntax proposal doesn't change that.
- WebFreak001 (3/12) Dec 10 2021 if that's your pain point, check out this proposal here:
- Ogi (11/13) Dec 14 2021 It’s not just my pain point though. We need to convert stuff to
- WebFreak001 (15/28) Dec 14 2021 no this proposal does not suggest moving any functionality into
- bauss (17/49) Dec 14 2021 While I completely understand the proposal then I think it's the
- WebFreak001 (30/48) Dec 14 2021 I think the complexity for the syntax and the language itself is
- zjh (2/3) Dec 14 2021 Is d as complex as `C++`?
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (22/25) Dec 14 2021 Depends on what you want to do. You can write simpler code in D,
- zjh (4/4) Dec 14 2021 On Tuesday, 14 December 2021 at 11:40:46 UTC, Ola Fosheim Grøstad
- rumbu (10/13) Dec 14 2021 There are around 90 keywords in C++ 20, from which 11 are
- bachmeier (10/27) Dec 14 2021 The saying about C++ has always been that it's a nice language if
- zjh (5/9) Dec 14 2021 `C++` has the baggage of the past(`Strengths/weaknesses`), so is
- Nick Treleaven (13/18) Dec 14 2021 static mostly comes from C++.
- deadalnix (2/5) Dec 14 2021 If we are honest, it probably similar at this point.
- zjh (2/3) Dec 14 2021 `Learn` from each other and `copy` from each other.
- bachmeier (6/9) Dec 14 2021 +1 I tuned out the whole discussion when I saw where it was
- Ogi (4/9) Dec 14 2021 I was referring to YAIDIP. According to it, istring should be
- WebFreak001 (12/22) Dec 14 2021 ah right you mean for the built-in istring usage in the compiler
- Ogi (8/19) Dec 14 2021 My point is, if the compiler has to implement istring processor
- WebFreak001 (10/32) Dec 14 2021 ah yeah I could see that work. I think it would only work at
- Ogi (6/11) Dec 14 2021 Ouch, you’re right, we can’t reuse `stringof` for this. Some
- Steven Schveighoffer (18/43) Dec 14 2021 pramga(msg) and mixin do not need implementations of `std.conv.text`.
- ManKey (14/15) Dec 10 2021 IMHO, this can be done through string mixins. But mixins have a
- rikki cattermole (18/20) Dec 14 2021 I am against it.
- WebFreak001 (20/43) Dec 14 2021 what do you mean with this? Memory management isn't part of the
- Adam D Ruppe (5/7) Dec 14 2021 Not necessarily - the string literal portions ARE available at
- Daniel N (7/11) Dec 14 2021 Then why isn't
- WebFreak001 (16/28) Dec 14 2021 ```d
- Daniel N (17/23) Dec 14 2021 I assumed it works with alias/variadic params...?
- Paul Backus (10/35) Dec 14 2021 It works for variables, but not arbitrary expressions. For
- deadalnix (8/50) Dec 16 2021 So passing a raw a should work (it's an alias parameter).
- Adam D Ruppe (11/14) Dec 16 2021 I wrote about that back in 2019, indeed, at that point, it was my
- bauss (3/17) Dec 16 2021 And nobody will ever agree, so we just have to somehow stick with
- Abdulhaq (30/32) Dec 14 2021 To a give another POV, from a polyglot background, I'd say there
We had an argument on the discord about the [YAIDIP](https://github.com/John-Colvin/YAIDIP) proposal and a simpler syntax form `identifier""` based on Ola Fosheim Grøstad's proposal, and similar to JavaScript's template string syntax. We came to the conclusion that the simpler syntax would just be that - a simpler syntax - and still require the YAIDIP, but with that give nice improvement opportunities. The simpler syntax would be an additional special function calling syntax (only valid for functions accepting the interpolated strings with the header as suggested by YAIDIP) Example: ```d string text(T...)(T args) if (isInterpolatedString!T) { ... } // could then be called: text"Hello $name!"; // translates to: text(i"Hello $name!"); // translates to: text(InterpolationHeader!("Hello ", "name", "!"), "Hello ", name, "!"); ``` For any new user the `text(i"Hello $name!")` or `i"Hello $name!".text` syntax could be daunting for regular use, possibly even hindering the adaption of interpolated strings for regular string usage. Like the `str.to!int` syntax has proven an advantage over `str.to!(int)` and how `foo.filter!isNumber.map!...` has proven advantages over `foo.filter!isNumber().map!...()`, these interpolated string functions would be useful in everyday application by GC users, with phobos functions like `text` or `format`, or by any other users with custom functions, and drive adoption of the YAIDIP interpolated string suggestion in user code. advantages of the simple syntax: - very easy syntax on the common GC-use of just creating a string from an interpolated string by a user: `setContent(text"Hello $name!", text"Welcome on your profile, $name.")` - familiar to JS developers having used their [template strings](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) - the return types of the handling functions can be regular structs (non-templated) and be used with functions accepting them to ensure type-safety and also allow exporting the functions in DLLs / static compiled libraries disadvantages: - not usable in template arguments with type arguments (like `foo!i"$bar $int"`) - need to use the `i` strings there - could clash with existing `i""`/`r""`/`q""` string types - these would need to be excluded as special cases Example how it could look using postgresql (dpq2) dub package: before: ```d double d = -1234.56789012345; string text = "first line\nsecond line"; Nullable!string nullString; int[][] arrs = [[1, 2, 3], [4, 5, 6]]; QueryParams p; p.sqlCommand = "SELECT "~ "$1::double precision as double_field, "~ "$2::text, "~ "$3::text as null_field, "~ "array['first', 'second', NULL]::text[] as array_field, "~ "$4::integer[] as multi_array, "~ `'{"float_value": 123.456,"text_str": "text string"}'::json as json_value`; p.argsVariadic( d, text, nullString, arrs ); auto r = conn.execParams(p); ``` after YAIDIP: ```d double d = -1234.56789012345; string text = "first line\nsecond line"; Nullable!string nullString; int[][] arrs = [[1, 2, 3], [4, 5, 6]]; QueryParams sql(T...)(T interpolatedString) { /* process the fields here, create string with incrementing variables, calling argsVariadic on the QueryParams object and returning it */ } QueryParams p = sql(i`SELECT $d::double precision as double_field, $text::text, $nullString::text as null_field, array['first', 'second', NULL]::text[] as array_field, $arrs::integer[] as multi_array, '{"float_value": 123.456,"text_str": "text string"}'::json as json_value`); auto r = conn.execParams(p); ``` using the simple syntax would allow you then writing `` sql`...` `` instead of ``sql(i`...`)`` Some code-bases (internal usage in packages/programs or in company code-bases) could opt for a really tiny name like `alias T = std.conv.text; string s = T"Hello $name!"`. The formal definition for this short syntax could either be ``` InterpolatedStringCall: Identifier " DoubleQuotedCharacters_opt " StringPostfix_opt Identifier ` WysiwygCharacters_opt ` StringPostfix_opt ``` allowing only simple identifiers or ``` InterpolatedStringCall: Expression " DoubleQuotedCharacters_opt " StringPostfix_opt Expression ` WysiwygCharacters_opt ` StringPostfix_opt ``` allowing any arbitrary expressions, immediately followed by a string like `(foo("hello")) " world"` which is then interpreted like an interpolated string. What do you think? Would this be essential for interpolated string adoption in user code or be useless?
Dec 09 2021
On Thursday, 9 December 2021 at 21:06:11 UTC, WebFreak001 wrote:We had an argument on the discord about the [YAIDIP](https://github.com/John-Colvin/YAIDIP) proposal and a simpler syntax form `identifier""` based on Ola Fosheim Grøstad's proposal, and similar to JavaScript's template string syntax.It is nice to see that you are thinking of ways to make this more user (newbie) friendly. What you propose isn't what I suggested though, but that is fine. (I suggested something more generic which would be similar to what you would do to support user-provided literals like ```100kg```, ```3.14rad```, ```100USD``` and where you would validate syntax and extract parameters in a customized way (think regexp), but there are many ways to Rome. :-)
Dec 09 2021
On Thursday, 9 December 2021 at 21:39:57 UTC, Ola Fosheim Grøstad wrote:but there are many ways to Rome. :-)Many ROADS… (sigh)
Dec 09 2021
On Thursday, 9 December 2021 at 21:06:11 UTC, WebFreak001 wrote:What do you think? Would this be essential for interpolated string adoption in user code or be useless?I'd be happier if interpolated strings were removed completely. The idea that they are more readable and convenient, is entirely subjective. IMO .. they are a completely unnecessary, additional cognitive load - as now you have to deal with the possibility of code having both composite AND interpolated strings. Interpolated strings..be gone!
Dec 09 2021
On Thursday, 9 December 2021 at 22:17:14 UTC, forkit wrote:IMO .. they are a completely unnecessary, additional cognitive load - as now you have to deal with the possibility of code having both composite AND interpolated strings.I understand your viewpoint, but imagine if you actually had a formal grammar describing all legal strings for a particular interpolated string type. That would allow you to get high quality IDE support where you would get autocompletion, suggestions and early identification of spelling errors. Such tooling is reducing cognitive load and saving time.
Dec 09 2021
On Thursday, 9 December 2021 at 22:39:13 UTC, Ola Fosheim Grøstad wrote:That would allow you to get high quality IDE support where you would get autocompletion, suggestions and early identification of spelling errors. Such tooling is reducing cognitive load and saving time.My experience with such tooling, is that they create extra cognitive load, to the point where I can no longer use them (mostly cause I can no longer work out how to disable all the crap that comes with them). Instead of focusing on my keystrokes, I end up seeing all kinds of things popping up, all over the place, all the f$HV time .. in all kinds of different colors!!
Dec 09 2021
On Friday, 10 December 2021 at 04:08:44 UTC, forkit wrote:Instead of focusing on my keystrokes, I end up seeing all kinds of things popping up, all over the place, all the f$HV time .. in all kinds of different colors!!So you turn it off and request help by hitting ctrl-space instead? Anyway, a key advantage you get, when having appropriately typed strings, is that you can add string validation to the semantic server that adds language support for the IDE. This can save a lot of time for many programmers. That alone is a good reason to prefer sql"" over i"".
Dec 10 2021
On Thursday, 9 December 2021 at 21:06:11 UTC, WebFreak001 wrote:The simpler syntax would be an additional special function calling syntax (only valid for functions accepting the interpolated strings with the header as suggested by YAIDIP) Example: ```d string text(T...)(T args) if (isInterpolatedString!T) { ... } // could then be called: text"Hello $name!"; // translates to: text(i"Hello $name!"); // translates to: text(InterpolationHeader!("Hello ", "name", "!"), "Hello ", name, "!"); ```This is much better. You'll note that the `i""` doesn't need to be backed in the language anymore with that construct and can be written as a library, if you define the rewrites the other way around.
Dec 10 2021
On Thursday, 9 December 2021 at 21:06:11 UTC, WebFreak001 wrote:For any new user the `text(i"Hello $name!")` or `i"Hello $name!".text` syntax could be daunting for regular use, possibly even hindering the adaption of interpolated strings for regular string usage.Not only that, you’ll have to import `std.cov` or `std.format` whenever you want to get a string out of an istring. Kinda defeats the purpose of string interpolation as a language feature.
Dec 10 2021
On Friday, 10 December 2021 at 13:51:16 UTC, Ogi wrote:Not only that, you’ll have to import `std.cov` or `std.format` whenever you want to get a string out of an istring.This syntax proposal doesn't change that. And it is trivial to make this convenient anyway.
Dec 10 2021
On Friday, 10 December 2021 at 13:51:16 UTC, Ogi wrote:On Thursday, 9 December 2021 at 21:06:11 UTC, WebFreak001 wrote:if that's your pain point, check out this proposal here: https://forum.dlang.org/thread/kivjspiezjvqxjkhiugj forum.dlang.org :)For any new user the `text(i"Hello $name!")` or `i"Hello $name!".text` syntax could be daunting for regular use, possibly even hindering the adaption of interpolated strings for regular string usage.Not only that, you’ll have to import `std.cov` or `std.format` whenever you want to get a string out of an istring. Kinda defeats the purpose of string interpolation as a language feature.
Dec 10 2021
On Friday, 10 December 2021 at 18:39:32 UTC, WebFreak001 wrote:if that's your pain point, check out this proposal here: https://forum.dlang.org/thread/kivjspiezjvqxjkhiugj forum.dlang.org :)It’s not just my pain point though. We need to convert stuff to strings all the time. For example, every time we want a meaningful message in an assertion or an exception. Many Phobos modules have to import `std.format` or `std.conv` just for that. To my understanding, this proposal already requires moving `text` functionality into compiler (if it’s not there already, I don’t know). So why not just make one more step forward and allow converting istrings to strings? If implicit conversion is too much to ask for, it could be an explicit cast to string, or some property. Maybe `stringof` should do exactly that?
Dec 14 2021
On Tuesday, 14 December 2021 at 09:10:07 UTC, Ogi wrote:On Friday, 10 December 2021 at 18:39:32 UTC, WebFreak001 wrote:no this proposal does not suggest moving any functionality into the compiler. It suggests to add the istrings (tuples with header) as described in the YAIDIP and have special function calling syntax (`functionName"istring contents"`) that will call any function, that accepts an istring as only argument. The `text` function from `std.conv` would implement an overload accepting an istring, which can then be called `text"istring contents"` (same as `text(i"istring contents")`) and be the idiomatic string building function using the GC. Then with the other linked proposal you could add `std.conv` (or a custom wrapper that only imports `std.conv:text`, maybe aliased) as default-import to all files in your project, so you can just type `text"istring contents"` to make strings without needing to import std.conv anywhere.if that's your pain point, check out this proposal here: https://forum.dlang.org/thread/kivjspiezjvqxjkhiugj forum.dlang.org :)It’s not just my pain point though. We need to convert stuff to strings all the time. For example, every time we want a meaningful message in an assertion or an exception. Many Phobos modules have to import `std.format` or `std.conv` just for that. To my understanding, this proposal already requires moving `text` functionality into compiler (if it’s not there already, I don’t know). So why not just make one more step forward and allow converting istrings to strings? If implicit conversion is too much to ask for, it could be an explicit cast to string, or some property. Maybe `stringof` should do exactly that?
Dec 14 2021
On Tuesday, 14 December 2021 at 09:35:27 UTC, WebFreak001 wrote:On Tuesday, 14 December 2021 at 09:10:07 UTC, Ogi wrote:While I completely understand the proposal then I think it's the wrong approach as it adds an infinite amount of complexity for something that barely solves any issues that exist today. Arguably while it solves some problems it's definitely going to introduce new issues with it. Has D forgotten Scott's talk, along with the common saying that sometimes less is more? D has so many concepts that it's almost impossible to wrap your head around D idioms and be an expert at D since there are so many edge-cases for each feature, so many issues that each feature tries to solve. Every feature D gets added is always added in the most complex way possible to solve as many problems as possible, instead of just solving a handful of problems that are mostly relevant then D tries to solve ALL problems, relevant or not. It's ultimately D's downfall that features are too complex.On Friday, 10 December 2021 at 18:39:32 UTC, WebFreak001 wrote:no this proposal does not suggest moving any functionality into the compiler. It suggests to add the istrings (tuples with header) as described in the YAIDIP and have special function calling syntax (`functionName"istring contents"`) that will call any function, that accepts an istring as only argument. The `text` function from `std.conv` would implement an overload accepting an istring, which can then be called `text"istring contents"` (same as `text(i"istring contents")`) and be the idiomatic string building function using the GC. Then with the other linked proposal you could add `std.conv` (or a custom wrapper that only imports `std.conv:text`, maybe aliased) as default-import to all files in your project, so you can just type `text"istring contents"` to make strings without needing to import std.conv anywhere.if that's your pain point, check out this proposal here: https://forum.dlang.org/thread/kivjspiezjvqxjkhiugj forum.dlang.org :)It’s not just my pain point though. We need to convert stuff to strings all the time. For example, every time we want a meaningful message in an assertion or an exception. Many Phobos modules have to import `std.format` or `std.conv` just for that. To my understanding, this proposal already requires moving `text` functionality into compiler (if it’s not there already, I don’t know). So why not just make one more step forward and allow converting istrings to strings? If implicit conversion is too much to ask for, it could be an explicit cast to string, or some property. Maybe `stringof` should do exactly that?
Dec 14 2021
On Tuesday, 14 December 2021 at 09:50:15 UTC, bauss wrote:On Tuesday, 14 December 2021 at 09:35:27 UTC, WebFreak001 wrote:I think the complexity for the syntax and the language itself is quite little - and it's basically the same thing as JS template string literals too, but with the special ignore cases for letters i/r/q. It's not going to solve any issues if nobody implements it. It's completely just an extension to the language, but then is going to be a big help to making both more pretty code with `text` The implementation of these functions is going to be a little complex.[...]While I completely understand the proposal then I think it's the wrong approach as it adds an infinite amount of complexity for something that barely solves any issues that exist today.Arguably while it solves some problems it's definitely going to introduce new issues with it.I can see that the new istring calling syntax could introduce issues if we want to add more string types through prefixes in the future, but I think that would be worth it for a quite versatile feature. The feature in other languages (like JS) has shown great use-cases, an example: https://github.com/kay-is/awesome-tagged-templates ^ that link contains lots of cool examples we could have in D like that too. Some type-safe data structure creation helper, some string / template language processors with nicer syntax, some useful every-day utilities. I think overall it will solve more issues than introducing new ones.Has D forgotten Scott's talk, along with the common saying that sometimes less is more? D has so many concepts that it's almost impossible to wrap your head around D idioms and be an expert at D since there are so many edge-cases for each feature, so many issues that each feature tries to solve. Every feature D gets added is always added in the most complex way possible to solve as many problems as possible, instead of just solving a handful of problems that are mostly relevant then D tries to solve ALL problems, relevant or not. It's ultimately D's downfall that features are too complex.it's a complex feature. However you don't really care about its implementation or complexity unless you want to implement a function for it yourself. All the average user might even want to think about is `text"..."`, which you could look at like it's special language syntax. It's something library authors can use and document to make more readable, better library functions. Overall I think there is more benefit in adding this than not adding this.
Dec 14 2021
On Tuesday, 14 December 2021 at 09:50:15 UTC, bauss wrote:It's ultimately D's downfall that features are too complex.Is d as complex as `C++`?
Dec 14 2021
On Tuesday, 14 December 2021 at 11:14:03 UTC, zjh wrote:On Tuesday, 14 December 2021 at 09:50:15 UTC, bauss wrote:Depends on what you want to do. You can write simpler code in D, often the syntax can be more compact in D. However, C++ is adding features that make more convoluted C++-constructs unnecessary, but as a programmer you have to figure out what to not use since almost nothing is removed from C++. So it is hard for beginners to figure out what not to do, and what to do. D is also increasing in complexity over time, often times I think that is because shortcuts are taken in the design and implementation. The evolution of C++ is driven by the spec and not the implementation, so some features makes it into C++ that greatly improves the language even though some compilers have to be changed quite a bit. But evolution in C++ moves in many directions, because it is designed by working-groups of different people. So it does not present a homogeneous "philosophy". It would be much easier for D to work towards a homogeneous whole, but it has to be a conscious strategy because one can easily be tempted to fan out in all kinds of directions (by demands and DIPs etc).It's ultimately D's downfall that features are too complex.Is d as complex as `C++`?
Dec 14 2021
On Tuesday, 14 December 2021 at 11:40:46 UTC, Ola Fosheim Grøstad wrote: I'm always using `/std:latest` in `C++`. and `2.098` in `d`.
Dec 14 2021
On Tuesday, 14 December 2021 at 11:14:03 UTC, zjh wrote:On Tuesday, 14 December 2021 at 09:50:15 UTC, bauss wrote:There are around 90 keywords in C++ 20, from which 11 are alternative names for operators. There are rare cases when a keyword in C++ can have a different meaning depending of the context. We have 100 keywords in D and many of them have multiple meanings (scope, static, if, is, in, out, const, do, enum, return) C++ is not necessary a complex language, STL usage and associated idioms makes it complex. If you look at some C++ code before Stepanov stepped in, it looks really nice and comprehensible :)It's ultimately D's downfall that features are too complex.Is d as complex as `C++`?
Dec 14 2021
On Tuesday, 14 December 2021 at 12:29:57 UTC, rumbu wrote:On Tuesday, 14 December 2021 at 11:14:03 UTC, zjh wrote:The saying about C++ has always been that it's a nice language if you stick to a subset of its features. The problem is that everyone needs a different subset. I personally don't have a problem with D's complexity since it's easy to ignore most of the language. The other problem I had with C++ was the need to be a language lawyer. You really have to understand the complete specification of the features you're using to avoid having it blow up on you. You can't easily program in C++ without a shelf full of Scott Myers books. I don't feel that way with D.On Tuesday, 14 December 2021 at 09:50:15 UTC, bauss wrote:There are around 90 keywords in C++ 20, from which 11 are alternative names for operators. There are rare cases when a keyword in C++ can have a different meaning depending of the context. We have 100 keywords in D and many of them have multiple meanings (scope, static, if, is, in, out, const, do, enum, return) C++ is not necessary a complex language, STL usage and associated idioms makes it complex. If you look at some C++ code before Stepanov stepped in, it looks really nice and comprehensible :)It's ultimately D's downfall that features are too complex.Is d as complex as `C++`?
Dec 14 2021
On Tuesday, 14 December 2021 at 12:29:57 UTC, rumbu wrote:C++ is not necessary a complex language, STL usage and associated idioms makes it complex. If you look at some C++ code before Stepanov stepped in, it looks really nice and comprehensible :)`C++` has the baggage of the past(`Strengths/weaknesses`), so is D. If `d` strengthen the `binding` with C++ and port the C++ `popular` library, it must be very good.
Dec 14 2021
On Tuesday, 14 December 2021 at 12:29:57 UTC, rumbu wrote:We have 100 keywords in D and many of them have multiple meanings (scope, static, if, is, in, out, const, do, enum, return)static mostly comes from C++. The only one of those D added that isn't natural and consistent is enum for manifest constant. I grant you some leeway for the unary `is` type check, but it still seems a natural extension from the binary form. (It is easy to read and understand).C++ is not necessary a complex language, STL usage and associated idioms makes it complex.If you compare the spec for the subset of D which C++ can implement, I think you will find it is more complex than the spec for D. References and lambdas for example. When designing a language, minimizing the set of keywords is not necessarily a good goal, the opposite is often true. You want code to look obvious. There are often tricks to reuse keywords, I'm glad D generally doesn't do that.
Dec 14 2021
On Tuesday, 14 December 2021 at 11:14:03 UTC, zjh wrote:On Tuesday, 14 December 2021 at 09:50:15 UTC, bauss wrote:If we are honest, it probably similar at this point.It's ultimately D's downfall that features are too complex.Is d as complex as `C++`?
Dec 14 2021
On Tuesday, 14 December 2021 at 13:40:02 UTC, deadalnix wrote:If we are honest, it probably similar at this point.`Learn` from each other and `copy` from each other.
Dec 14 2021
On Tuesday, 14 December 2021 at 09:50:15 UTC, bauss wrote:While I completely understand the proposal then I think it's the wrong approach as it adds an infinite amount of complexity for something that barely solves any issues that exist today.+1 I tuned out the whole discussion when I saw where it was going. It'd be nice to introduce features that improve the language without worrying about covering every possible edge case that could come up. Syntax, simplicity, and convenience are valuable.
Dec 14 2021
On Tuesday, 14 December 2021 at 09:35:27 UTC, WebFreak001 wrote:no this proposal does not suggest moving any functionality into the compiler. It suggests to add the istrings (tuples with header) as described in the YAIDIP and have special function calling syntax (`functionName"istring contents"`) that will call any function, that accepts an istring as only argument.I was referring to YAIDIP. According to it, istring should be allowed in `mixin`, `pragma(msg)` and `assert` (missed this one). This requires reimplementing `text` in the compiler.
Dec 14 2021
On Tuesday, 14 December 2021 at 11:02:58 UTC, Ogi wrote:On Tuesday, 14 December 2021 at 09:35:27 UTC, WebFreak001 wrote:ah right you mean for the built-in istring usage in the compiler it needs to be implemented. I don't think it's such a big problem though, as the phobos implementation would also just be: (a little simplified) ```d auto text(istring...)(istring s) if (isIString!istring) { return text(s[1 .. $]); // removes special __header, just concatenate rest } ```no this proposal does not suggest moving any functionality into the compiler. It suggests to add the istrings (tuples with header) as described in the YAIDIP and have special function calling syntax (`functionName"istring contents"`) that will call any function, that accepts an istring as only argument.I was referring to YAIDIP. According to it, istring should be allowed in `mixin`, `pragma(msg)` and `assert` (missed this one). This requires reimplementing `text` in the compiler.
Dec 14 2021
On Tuesday, 14 December 2021 at 11:15:02 UTC, WebFreak001 wrote:ah right you mean for the built-in istring usage in the compiler it needs to be implemented. I don't think it's such a big problem though, as the phobos implementation would also just be: (a little simplified) ```d auto text(istring...)(istring s) if (isIString!istring) { return text(s[1 .. $]); // removes special __header, just concatenate rest } ```My point is, if the compiler has to implement istring processor anyway, why not make it a language feature: ```D //look ma no imports int bottleCount = 99; string str = i"$(bottleCount) bottles on the wall".stringof; assert(str == "99 bottles on the wall");
Dec 14 2021
On Tuesday, 14 December 2021 at 12:41:27 UTC, Ogi wrote:On Tuesday, 14 December 2021 at 11:15:02 UTC, WebFreak001 wrote:ah yeah I could see that work. I think it would only work at compile time though if you use .stringof (otherwise you need a runtime function - like text - that allocates the memory somehow, which is none of the compiler's business)ah right you mean for the built-in istring usage in the compiler it needs to be implemented. I don't think it's such a big problem though, as the phobos implementation would also just be: (a little simplified) ```d auto text(istring...)(istring s) if (isIString!istring) { return text(s[1 .. $]); // removes special __header, just concatenate rest } ```[...] ```D //look ma no imports int bottleCount = 99; string str = i"$(bottleCount) bottles on the wall".stringof; assert(str == "99 bottles on the wall");My point is, if the compiler has to implement istring processor anyway, why not make it a language feature:Having the `text"..."` syntax IS a language feature, you just need an implementation, which phobos provides and is bundled with every distribution of D. (have it in std.conv or add it to object if you aren't interested in the other proposal to have default imports specified as compiler flags)
Dec 14 2021
On Tuesday, 14 December 2021 at 12:55:30 UTC, WebFreak001 wrote:I think it would only work at compile time though if you use .stringofOuch, you’re right, we can’t reuse `stringof` for this. Some other name then, like `str` or something.otherwise you need a runtime function - like text - that allocates the memory somehow, which is none of the compiler's businessYAIDIP requires istring processing both at compile-time (`mixin` and `static assert`) and runtime (regular `assert` and `pragma(msg)`).
Dec 14 2021
On 12/14/21 6:15 AM, WebFreak001 wrote:On Tuesday, 14 December 2021 at 11:02:58 UTC, Ogi wrote:pramga(msg) and mixin do not need implementations of `std.conv.text`. `pragma(msg, "x = ", x);` already works, just need it to ignore the header. `mixin("int y = ", x + 5, ";")` already works, just need it to ignore the header. assert would need some implementation of runtime output. But it's already in the library with `-checkaction=context`. It just needs to be exposed.On Tuesday, 14 December 2021 at 09:35:27 UTC, WebFreak001 wrote:no this proposal does not suggest moving any functionality into the compiler. It suggests to add the istrings (tuples with header) as described in the YAIDIP and have special function calling syntax (`functionName"istring contents"`) that will call any function, that accepts an istring as only argument.I was referring to YAIDIP. According to it, istring should be allowed in `mixin`, `pragma(msg)` and `assert` (missed this one). This requires reimplementing `text` in the compiler.ah right you mean for the built-in istring usage in the compiler it needs to be implemented. I don't think it's such a big problem though, as the phobos implementation would also just be: (a little simplified) ```d auto text(istring...)(istring s) if (isIString!istring) { return text(s[1 .. $]); // removes special __header, just concatenate rest } ```The DIP is designed specifically to work with `text` as-is. You don't need a special overload (because the header has a `toString` that returns ""). This was inherited from our DIP. As for the specialized call syntax, I don't think we need it. As for implementing some `text`-like thing in druntime, we already have some of it, I think it would be reasonable to include something in object.d that does a straightforward conversion when you don't want to use std.format. The only complex one is floating point. This all can be done AFTER the DIP is accepted anyway. -Steve
Dec 14 2021
On Thursday, 9 December 2021 at 21:06:11 UTC, WebFreak001 wrote:We had an argument on the discord about theIMHO, this can be done through string mixins. But mixins have a large syntax (This is very strange for a language in which closures can be written as `{code}`.). If it was possible to write instead of `mixin(i!"2 + 3 = ${2 + 3}")` something like this `#i!"2 + 3 = ${2 + 3}"`, then this DIP would not be needed. Then it would be possible not only to do string interpolation, for example: ```d JSON j = #jsonlit!q{ "any" ~ "d_expr": 5 + 6, "key": data.map!(func).array, }; ```
Dec 10 2021
On 10/12/2021 10:06 AM, WebFreak001 wrote:What do you think? Would this be essential for interpolated string adoption in user code or be useless?I am against it. Due to it marrying a memory management+formatting strategy to the language. One way to do this is to support ``Identifier Token`` UFCS pattern which would allow this to "just work" except generically. So if you want to get data from your database? auto data = dbcon.sql`SELECT * FROM table where field = "%value$arg"`; That could pass it in as an interpolated string. However, that could be extremely confusing to the user as this is a function call, which takes a string... yet its actually something very different. Like why doesn't adding the brackets allow for that to work? ext. ext. One reason I would like this pattern even though I don't think we should ever have it is so that I can have hex strings back. Super useful during code generation and table generation for large data sets (now days I've found that std.base64 does an excellent job at this, even with a little bit of fluff). ubyte[] data = hex"AABBCC"; // ok
Dec 14 2021
On Tuesday, 14 December 2021 at 14:01:56 UTC, rikki cattermole wrote:On 10/12/2021 10:06 AM, WebFreak001 wrote:what do you mean with this? Memory management isn't part of the language or the proposal here (you need to use std.conv : `text`) and the syntax you propose here is the exact syntax proposed in the post. I don't quite get where you disagree or why you are against it from this paragraph at least.What do you think? Would this be essential for interpolated string adoption in user code or be useless?I am against it. Due to it marrying a memory management+formatting strategy to the language. One way to do this is to support ``Identifier Token`` UFCS pattern which would allow this to "just work" except generically.So if you want to get data from your database? auto data = dbcon.sql`SELECT * FROM table where field = "%value$arg"`; That could pass it in as an interpolated string. However, that could be extremely confusing to the user as this is a function call, which takes a string... yet its actually something very different. Like why doesn't adding the brackets allow for that to work? ext. ext.this is the same as JS template literal syntax - it's another way of calling a function. Given how different it looks from regular function calls, I don't think you would be very confused. The compiler would also tell you that you are trying to pass a string to a function that checks for an istring. Just like currently `a.ufcsFun(b)` works but `&a.ufcsFun` to take its address doesn't, even though `a.memberFun(b)` works and `&a.memberFun` takes its address - I don't think anyone is confused about it, or at least it's easy to learn why the UFCS one doesn't work, just as it will with this proposal.One reason I would like this pattern even though I don't think we should ever have it is so that I can have hex strings back. Super useful during code generation and table generation for large data sets (now days I've found that std.base64 does an excellent job at this, even with a little bit of fluff). ubyte[] data = hex"AABBCC"; // okI was thinking about this as well - it would work but would run at runtime. I'm not a fan of using it just for static data and think `hexString!"..."` is better for that.
Dec 14 2021
On Tuesday, 14 December 2021 at 15:58:21 UTC, WebFreak001 wrote:I was thinking about this as well - it would work but would run at runtime.Not necessarily - the string literal portions ARE available at compile time and the function could just choose to return those as a ctfe calculation. That's one of the deeper layers of good about this dip.
Dec 14 2021
On Tuesday, 14 December 2021 at 15:58:21 UTC, WebFreak001 wrote:Then why isn't text!i"..." ok? Why do we need multiple i"..." f"..." ?ubyte[] data = hex"AABBCC"; // okI was thinking about this as well - it would work but would run at runtime. I'm not a fan of using it just for static data and think `hexString!"..."` is better for that.
Dec 14 2021
On Tuesday, 14 December 2021 at 16:04:58 UTC, Daniel N wrote:On Tuesday, 14 December 2021 at 15:58:21 UTC, WebFreak001 wrote:```d string name = readln(); auto greeting = text!i"hello $name!"; ``` expands to ```d string name = readln(); auto greeting = text!(__header!..., "hello ", name, "!"); ``` that wouldn't work because name is a runtime variable and you are trying to use it as a template parameter here. You would need to do `text(i!"hello $name!")` or `i"hello $name!".text` for the YAIDIP to work or as this post suggested a new calling syntax that extends to that: `text"hello $name!"`Then why isn't text!i"..." ok? Why do we need multiple i"..." f"..." ?ubyte[] data = hex"AABBCC"; // okI was thinking about this as well - it would work but would run at runtime. I'm not a fan of using it just for static data and think `hexString!"..."` is better for that.
Dec 14 2021
On Tuesday, 14 December 2021 at 16:15:28 UTC, WebFreak001 wrote:```d string name = readln(); auto greeting = text!(__header!..., "hello ", name, "!"); ``` that wouldn't work because name is a runtime variable and you are trying to use it as a template parameter here.I assumed it works with alias/variadic params...? ```d import std; int sum(Vs...)() { int sum = 0; foreach(v ; Vs) sum += v; return sum; } void main() { int a = to!int(readln()); sum!a.writeln; } ```
Dec 14 2021
On Tuesday, 14 December 2021 at 20:07:43 UTC, Daniel N wrote:On Tuesday, 14 December 2021 at 16:15:28 UTC, WebFreak001 wrote:It works for variables, but not arbitrary expressions. For example, if you wrote ```d sum!(a, a+1).writeln; ``` ...then you would get an error: ``` Error: variable `a` cannot be read at compile time ``````d string name = readln(); auto greeting = text!(__header!..., "hello ", name, "!"); ``` that wouldn't work because name is a runtime variable and you are trying to use it as a template parameter here.I assumed it works with alias/variadic params...? ```d import std; int sum(Vs...)() { int sum = 0; foreach(v ; Vs) sum += v; return sum; } void main() { int a = to!int(readln()); sum!a.writeln; } ```
Dec 14 2021
On Tuesday, 14 December 2021 at 21:06:19 UTC, Paul Backus wrote:On Tuesday, 14 December 2021 at 20:07:43 UTC, Daniel N wrote:So passing a raw a should work (it's an alias parameter). Passing a+1 obviously doesn't as it is not a value that can be computed at compile time. Which lead me to think, can't we generate some kind of struct on the fly for the "${}" syntax? That would solve the problem and the end result would be supperior to the i solution (in fact, it would allow to implement the i solution as a library).On Tuesday, 14 December 2021 at 16:15:28 UTC, WebFreak001 wrote:It works for variables, but not arbitrary expressions. For example, if you wrote ```d sum!(a, a+1).writeln; ``` ...then you would get an error: ``` Error: variable `a` cannot be read at compile time ``````d string name = readln(); auto greeting = text!(__header!..., "hello ", name, "!"); ``` that wouldn't work because name is a runtime variable and you are trying to use it as a template parameter here.I assumed it works with alias/variadic params...? ```d import std; int sum(Vs...)() { int sum = 0; foreach(v ; Vs) sum += v; return sum; } void main() { int a = to!int(readln()); sum!a.writeln; } ```
Dec 16 2021
On Thursday, 16 December 2021 at 13:19:16 UTC, deadalnix wrote:So passing a raw a should work (it's an alias parameter).yeahWhich lead me to think, can't we generate some kind of struct on the fly for the "${}" syntax?I wrote about that back in 2019, indeed, at that point, it was my preference: http://dpldocs.info/this-week-in-d/Blog.Posted_2019_05_13.html#my-string-interpolation-proposal But it brings its own problems: this forces at least partial evaluation early which makes trouble with non-copyable types, breaks ref and aliases, and might be trouble tracking lifetime. It is a solidly decent plan but not quite full D potential. But like I've said before, all this stuff has been discussed to death. Some of us have been debating all this for years.
Dec 16 2021
On Thursday, 16 December 2021 at 13:31:07 UTC, Adam D Ruppe wrote:On Thursday, 16 December 2021 at 13:19:16 UTC, deadalnix wrote:And nobody will ever agree, so we just have to somehow stick with one implementation or it'll never happen.So passing a raw a should work (it's an alias parameter).yeahWhich lead me to think, can't we generate some kind of struct on the fly for the "${}" syntax?I wrote about that back in 2019, indeed, at that point, it was my preference: http://dpldocs.info/this-week-in-d/Blog.Posted_2019_05_13.html#my-string-interpolation-proposal But it brings its own problems: this forces at least partial evaluation early which makes trouble with non-copyable types, breaks ref and aliases, and might be trouble tracking lifetime. It is a solidly decent plan but not quite full D potential. But like I've said before, all this stuff has been discussed to death. Some of us have been debating all this for years.
Dec 16 2021
On Thursday, 9 December 2021 at 21:06:11 UTC, WebFreak001 wrote:We had an argument on the discord about the [YAIDIP](https://github.com/John-Colvin/YAIDIP) proposal and aTo a give another POV, from a polyglot background, I'd say there is a statement in the YAIDIP which is incorrect and somewhat skews the rest of the argument: ```The simplest use case of interpolated strings, and the most likely to be encountered in practice, is as argument to functions such as writeln, text, writefln, or format:``` Surely the simplest use case, and most likely to be encountered, is simply to build a well formatted string from a blend of string literals and local variables: ``` int x = 42; auto s = i"Let's interpolate $x!" ``` where s would be of string type. I use interpolated strings in numerous languages and I do so to present a clear expression to the reading developer of the intended format of the final string, and to keep the code tidy. In fact, I code like above specifically to avoid passing messy expressions as arguments to a following function call. I can see the power and attraction of the proposed design, but it has to be weighed against a syntax that satisfies the principle of least astonishment, as also identified in the same DIP. I'm also thinking that if tuples were more fully integrated and rationalised in the language then the benefits offered by this DIP regarding passing argument lists to string handling functions could be achieved in some other way using syntactically convenient unpacking of tuples into argument lists, but it's been a long time now since I used D in anger so if this part of my argument is just noise then... ignore it :-)
Dec 14 2021