digitalmars.D - mixin identifiers concept
- mesni (15/15) Jan 29 2022 ```d
- bauss (27/43) Jan 30 2022 I believe a DIP would be necessary, but to be honest I don't see
- Paul Backus (6/18) Jan 31 2022 Using `std.format` for this incurs a substantial compile-time
- bachmeier (8/29) Jan 31 2022 You have to balance that (which in the absence of benchmarks or
- Paul Backus (8/15) Jan 31 2022 This is a fair criticism of the original proposal. However,
- mesni (3/10) Feb 02 2022 IMHO, in the long term, reading code like this with C like format
- mesni (3/10) Feb 02 2022 IMHO, in the long term, reading code like this with C like format
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (7/12) Feb 02 2022 String mixins should be discouraged, not encouraged. Adding more
- Nick Treleaven (12/18) Feb 02 2022 String mixins can be used for declarations, expressions or types.
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (7/12) Feb 02 2022 If you have to use a *mixin* for an identifier on a regular basis
- Patrick Schluter (6/19) Feb 02 2022 Yes, exactly. Mixin variable names as used here is imho a code
- Nick Treleaven (8/10) Feb 02 2022 No one said that. It is only to replace using a mixin string for
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (5/8) Feb 05 2022 I agree with the concern for runtime performance, but if that
- Atila Neves (2/23) Feb 07 2022 mixin(`string file_`, name, ` = readText("`, name, `.txt");`);
- Quirin Schroll (23/67) Feb 07 2022 One big disadvantage interpolated strings have is you have to put
- Nick Treleaven (23/35) Jan 31 2022 A general feature for this has been suggested several times
```d static foreach(name; ["boo", "foo"]){ string file_#name = readText(name~".txt"); string file_#name } writeln(file_boo); writeln(boo); writeln(file_foo_info); ``` To make it easier to read/write code in D, I would introduce new mixins. These mixins can only represent identifiers. Also, the advantage of such mixins, the parser and semantic analysis will be able to detect some errors before the code is completely "opened". Also, I think they can speed up compilation.
Jan 29 2022
On Saturday, 29 January 2022 at 21:24:09 UTC, mesni wrote:```d static foreach(name; ["boo", "foo"]){ string file_#name = readText(name~".txt"); string file_#name } writeln(file_boo); writeln(boo); writeln(file_foo_info); ``` To make it easier to read/write code in D, I would introduce new mixins. These mixins can only represent identifiers. Also, the advantage of such mixins, the parser and semantic analysis will be able to detect some errors before the code is completely "opened". Also, I think they can speed up compilation.I believe a DIP would be necessary, but to be honest I don't see a reason for this. You can just do this which isn't really much less readable. ```d static foreach (name; ["boo", "foo"]) { mixin(`string file_%1$s = readText("%1$s.txt");`.format(name)); } writeln(file_boo); writeln(file_foo); ``` And if D ever gets interpolated strings then the whole format can be removed and it could probably become something like this: ```d static foreach (name; ["boo", "foo"]) { mixin(i`string file_$name = readText("$name.txt");`); } writeln(file_boo); writeln(file_foo); ``` So personally I don't see a reason for your suggestion to be added. I think it's just going to introduce more complexity than it's worth.
Jan 30 2022
On Monday, 31 January 2022 at 07:19:49 UTC, bauss wrote:I believe a DIP would be necessary, but to be honest I don't see a reason for this. You can just do this which isn't really much less readable. ```d static foreach (name; ["boo", "foo"]) { mixin(`string file_%1$s = readText("%1$s.txt");`.format(name)); } writeln(file_boo); writeln(file_foo); ```Using `std.format` for this incurs a substantial compile-time performance penalty--dozens of templates must be instantiated, memory must be allocated for CTFE, the format string must be validated, etc. If the mixin is inside a template which is itself instantiated many times, this overhead can really add up.
Jan 31 2022
On Monday, 31 January 2022 at 20:45:53 UTC, Paul Backus wrote:On Monday, 31 January 2022 at 07:19:49 UTC, bauss wrote:You have to balance that (which in the absence of benchmarks or other empirical evidence is a theoretical problem) against the horrendous cost in terms of complexity of the language. It's not just the syntax - which would be a substantial burden for new users - but also understanding the details of what it's doing. It's hard to see this being worthwhile for only gains in compilation time.I believe a DIP would be necessary, but to be honest I don't see a reason for this. You can just do this which isn't really much less readable. ```d static foreach (name; ["boo", "foo"]) { mixin(`string file_%1$s = readText("%1$s.txt");`.format(name)); } writeln(file_boo); writeln(file_foo); ```Using `std.format` for this incurs a substantial compile-time performance penalty--dozens of templates must be instantiated, memory must be allocated for CTFE, the format string must be validated, etc. If the mixin is inside a template which is itself instantiated many times, this overhead can really add up.
Jan 31 2022
On Tuesday, 1 February 2022 at 01:52:25 UTC, bachmeier wrote:You have to balance that (which in the absence of benchmarks or other empirical evidence is a theoretical problem) against the horrendous cost in terms of complexity of the language. It's not just the syntax - which would be a substantial burden for new users - but also understanding the details of what it's doing. It's hard to see this being worthwhile for only gains in compilation time.This is a fair criticism of the original proposal. However, allowing the standard string mixin syntax to be used for identifiers in declarations, as suggested by Nick Treleaven in [his reply][1], would bring the same benefits with significantly less complexity. [1]: https://forum.dlang.org/post/aznmkielsozvfgrzehoc forum.dlang.org
Jan 31 2022
On Tuesday, 1 February 2022 at 01:52:25 UTC, bachmeier wrote:You have to balance that (which in the absence of benchmarks or other empirical evidence is a theoretical problem) against the horrendous cost in terms of complexity of the language. It's not just the syntax - which would be a substantial burden for new users - but also understanding the details of what it's doing. It's hard to see this being worthwhile for only gains in compilation time.IMHO, in the long term, reading code like this with C like format will take more than memorizing a few rules.
Feb 02 2022
On Tuesday, 1 February 2022 at 01:52:25 UTC, bachmeier wrote:You have to balance that (which in the absence of benchmarks or other empirical evidence is a theoretical problem) against the horrendous cost in terms of complexity of the language. It's not just the syntax - which would be a substantial burden for new users - but also understanding the details of what it's doing. It's hard to see this being worthwhile for only gains in compilation time.IMHO, in the long term, reading code like this with C like format will take more than memorizing a few rules.
Feb 02 2022
On Monday, 31 January 2022 at 20:45:53 UTC, Paul Backus wrote:Using `std.format` for this incurs a substantial compile-time performance penalty--dozens of templates must be instantiated, memory must be allocated for CTFE, the format string must be validated, etc. If the mixin is inside a template which is itself instantiated many times, this overhead can really add up.String mixins should be discouraged, not encouraged. Adding more band aids or special cases is not the right approach. If compile time string processing is the root issue then one shouldn't solve that by changing the semantics of mixin(). That performance issue can be fixed by introducing classic string interpolation.
Feb 02 2022
On Wednesday, 2 February 2022 at 12:19:57 UTC, Ola Fosheim Grøstad wrote:String mixins should be discouraged, not encouraged. Adding more band aids or special cases is not the right approach.String mixins can be used for declarations, expressions or types. The special case is actually that they can't be used for an identifier. People even expect that to work - from the learn forum: https://forum.dlang.org/thread/ngfkwcyqjtnqhofoqrew forum.dlang.orgIf compile time string processing is the root issue then one shouldn't solve that by changing the semantics of mixin(). That performance issue can be fixed by introducing classic string interpolation.String interpolation would be pretty much just as bad for performance because it still requires the entire declaration to be put in a string, rather than just an identifier. That whole string needs to be formatted and turned into code, when we'd rather be reading code in the first place!
Feb 02 2022
On Wednesday, 2 February 2022 at 12:24:32 UTC, Nick Treleaven wrote:String interpolation would be pretty much just as bad for performance because it still requires the entire declaration to be put in a string, rather than just an identifier. That whole string needs to be formatted and turned into code, when we'd rather be reading code in the first place!If you have to use a *mixin* for an identifier on a regular basis then that suggests to me that something is wrong with the design of the application or that some other language feature is missing. *mixin* should be viewed as an emergency escape hatch compenstating for language deficiencies, not as a solution.
Feb 02 2022
On Wednesday, 2 February 2022 at 13:13:13 UTC, Ola Fosheim Grøstad wrote:On Wednesday, 2 February 2022 at 12:24:32 UTC, Nick Treleaven wrote:Yes, exactly. Mixin variable names as used here is imho a code smell. The variables are parametrized by a name and that is probably better solved by an array indexed on an enum, or a structure or even by an associative array.String interpolation would be pretty much just as bad for performance because it still requires the entire declaration to be put in a string, rather than just an identifier. That whole string needs to be formatted and turned into code, when we'd rather be reading code in the first place!If you have to use a *mixin* for an identifier on a regular basis then that suggests to me that something is wrong with the design of the application or that some other language feature is missing. *mixin* should be viewed as an emergency escape hatch compenstating for language deficiencies, not as a solution.
Feb 02 2022
On Wednesday, 2 February 2022 at 13:13:13 UTC, Ola Fosheim Grøstad wrote:If you have to use a *mixin* for an identifier on a regular basisNo one said that. It is only to replace using a mixin string for an entire declaration. If you hate mixin strings logically you should not oppose something which restricts their use to a much smaller scope. I do not buy any argument that it would encourage mixin strings. In metaprogramming you do what is necessary for best runtime performance.
Feb 02 2022
On Wednesday, 2 February 2022 at 16:24:25 UTC, Nick Treleaven wrote:much smaller scope. I do not buy any argument that it would encourage mixin strings. In metaprogramming you do what is necessary for best runtime performance.I agree with the concern for runtime performance, but if that really is an issue then maybe it would better to instead improve on the language rather than adding more string-manipulation.
Feb 05 2022
On Monday, 31 January 2022 at 20:45:53 UTC, Paul Backus wrote:On Monday, 31 January 2022 at 07:19:49 UTC, bauss wrote:mixin(`string file_`, name, ` = readText("`, name, `.txt");`);I believe a DIP would be necessary, but to be honest I don't see a reason for this. You can just do this which isn't really much less readable. ```d static foreach (name; ["boo", "foo"]) { mixin(`string file_%1$s = readText("%1$s.txt");`.format(name)); } writeln(file_boo); writeln(file_foo); ```Using `std.format` for this incurs a substantial compile-time performance penalty--dozens of templates must be instantiated, memory must be allocated for CTFE, the format string must be validated, etc. If the mixin is inside a template which is itself instantiated many times, this overhead can really add up.
Feb 07 2022
On Monday, 31 January 2022 at 07:19:49 UTC, bauss wrote:On Saturday, 29 January 2022 at 21:24:09 UTC, mesni wrote:One big disadvantage interpolated strings have is you have to put the full declaration in a string. No big deal for a statement, but if the name of a function depends on compile-time stuff, the whole function is a string. A much easier solution to this is allowing `mixin()` as an `Identifier` in general: ```diff Identifier: IdentifierStart IdentifierStart IdentifierChars + MixinExpression ``` So, you'd do ```d static foreach(name; ["boo", "foo"]) { enum string file_name_info = "file_" ~ name ~ "_info"; string mixin("file_", name) = readText(name ~ ".txt"); string mixin(file_name_info) = readText(name ~ ".meta"); auto mixin(name) = mixin(file_name_info).parseInfoFile; } ``````d static foreach(name; ["boo", "foo"]){ string file_#name = readText(name~".txt"); string file_#name } writeln(file_boo); writeln(boo); writeln(file_foo_info); ``` To make it easier to read/write code in D, I would introduce new mixins. These mixins can only represent identifiers. Also, the advantage of such mixins, the parser and semantic analysis will be able to detect some errors before the code is completely "opened". Also, I think they can speed up compilation.I believe a DIP would be necessary, but to be honest I don't see a reason for this. You can just do this which isn't really much less readable. ```d static foreach (name; ["boo", "foo"]) { mixin(`string file_%1$s = readText("%1$s.txt");`.format(name)); } writeln(file_boo); writeln(file_foo); ``` And if D ever gets interpolated strings then the whole format can be removed and it could probably become something like this: ```d static foreach (name; ["boo", "foo"]) { mixin(i`string file_$name = readText("$name.txt");`); } writeln(file_boo); writeln(file_foo); ``` So personally I don't see a reason for your suggestion to be added. I think it's just going to introduce more complexity than it's worth.
Feb 07 2022
On Monday, 7 February 2022 at 10:49:13 UTC, Quirin Schroll wrote:On Monday, 31 January 2022 at 07:19:49 UTC, bauss wrote:Yeah, I'm definitely not against mixin working for identifiers. My example was as a solution if it's never accepted.On Saturday, 29 January 2022 at 21:24:09 UTC, mesni wrote:One big disadvantage interpolated strings have is you have to put the full declaration in a string. No big deal for a statement, but if the name of a function depends on compile-time stuff, the whole function is a string. A much easier solution to this is allowing `mixin()` as an `Identifier` in general: ```diff Identifier: IdentifierStart IdentifierStart IdentifierChars + MixinExpression ``` So, you'd do ```d static foreach(name; ["boo", "foo"]) { enum string file_name_info = "file_" ~ name ~ "_info"; string mixin("file_", name) = readText(name ~ ".txt"); string mixin(file_name_info) = readText(name ~ ".meta"); auto mixin(name) = mixin(file_name_info).parseInfoFile; } ``````d static foreach(name; ["boo", "foo"]){ string file_#name = readText(name~".txt"); string file_#name } writeln(file_boo); writeln(boo); writeln(file_foo_info); ``` To make it easier to read/write code in D, I would introduce new mixins. These mixins can only represent identifiers. Also, the advantage of such mixins, the parser and semantic analysis will be able to detect some errors before the code is completely "opened". Also, I think they can speed up compilation.I believe a DIP would be necessary, but to be honest I don't see a reason for this. You can just do this which isn't really much less readable. ```d static foreach (name; ["boo", "foo"]) { mixin(`string file_%1$s = readText("%1$s.txt");`.format(name)); } writeln(file_boo); writeln(file_foo); ``` And if D ever gets interpolated strings then the whole format can be removed and it could probably become something like this: ```d static foreach (name; ["boo", "foo"]) { mixin(i`string file_$name = readText("$name.txt");`); } writeln(file_boo); writeln(file_foo); ``` So personally I don't see a reason for your suggestion to be added. I think it's just going to introduce more complexity than it's worth.
Feb 07 2022
On Monday, 7 February 2022 at 10:49:13 UTC, Quirin Schroll wrote:A much easier solution to this is allowing `mixin()` as an `Identifier` in general: ```diff Identifier: IdentifierStart IdentifierStart IdentifierChars + MixinExpression ``` So, you'd do ```d static foreach(name; ["boo", "foo"]) { enum string file_name_info = "file_" ~ name ~ "_info"; string mixin("file_", name) = readText(name ~ ".txt"); string mixin(file_name_info) = readText(name ~ ".meta"); auto mixin(name) = mixin(file_name_info).parseInfoFile; } ```This looks fantastic!
Feb 07 2022
On Saturday, 29 January 2022 at 21:24:09 UTC, mesni wrote:```d static foreach(name; ["boo", "foo"]){ string file_#name = readText(name~".txt"); string file_#name }A general feature for this has been suggested several times before by various people (initially in 2009!). (I noticed your syntax above seems to flip the meanings of the C preprocessor identifier is expected. It was mentioned in the `static foreach` DIP: https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1010.md#mixin-identifiers The nice thing about re-using string `mixin` syntax for this is that (since then) it can take multiple arguments which the compiler concatenates. So this would work: ```d static foreach(n; [1,2,3]) { int mixin("foo", n) = n; } assert(foo1 == 1); ```To make it easier to read/write code in D, I would introduce new mixins. These mixins can only represent identifiers. Also, the advantage of such mixins, the parser and semantic analysis will be able to detect some errors before the code is completely "opened". Also, I think they can speed up compilation.Yes, parsing would be a bit quicker vs putting the whole declaration in a string with CTFE string concatenation. Parsing error messages would be much easier to deal with, besides the likelihood of errors being lower anyway as the code would be much more readable.
Jan 31 2022