digitalmars.D - Getting code in strings: __EXPRESSION_OF__
- Quirin Schroll (58/58) Jul 18 2023 There are special keywords that decay into context-dependent
- Paul Backus (14/18) Jul 18 2023 The general-case replacement for this is a string mixin:
There are special keywords that decay into context-dependent strings or values, e.g. `__FILE__` and `__LINE__` which can be used as default arguments and make logging a breeze. For asserting, it would be nice to have access to the expression that was asserted on. My idea was to add `__EXPRESSIONS_OF__` which decays to an array literal that contains the tokens as strings of selected function arguments. There’s two ways it can be used: * `__EXPRESSIONS_OF__(`*comma-separated `Identifier`s*`)` to refer to (named) arguments. * `__EXPRESSIONS_OF__(`*comma-separated `ConditionalExpression`s*`)` to index (0-based) into the arguments. Of course, the number must be less than the number of arguments passed. (The `ConditionalExpression` must evaluate to an integer at compile-time.) Of course, if the list is of known length (which in ordinary code, it is), the resulting literal can be bound to a fixed-size array. As an example: ```d void myAssert(bool condition, lazy string message = "assert failed: ", string[1] expression = __EXPRESSIONS_OF__(condition)) { … } ``` The by-index referral is intended to make meta-programming easier, to have support for the case where the parameter isn’t really named (for whatever reason, which there are many, from linters not liking named parameters that aren’t used, to expansion of compile-time sequences). The result is available at compile-time and can be bound to a template argument: ```d void someTemplate(Ts..., Es = __EXPRESSIONS_OF__(args))(Ts args) { … } void someTemplate(Ts...)(Ts args, string[1] expr = __EXPRESSIONS_OF__(0)) { … } ``` What do you think? To a limited extent, it can be replicated using `alias` template parameters: ```d void assertEquals(alias value, T)(T expected) { if (value != expected) { import std.stdio; writeln(value.stringof, " had an unexpected value: ", value, " != ", expected); } } void main() { int x = 10; assertEquals!x(10); // silent assertEquals!x(11); // prints: x had an unexpected value: 10 != 11 } ``` However, that only works with identifiers.
Jul 18 2023
On Tuesday, 18 July 2023 at 13:33:49 UTC, Quirin Schroll wrote:To a limited extent, it can be replicated using `alias` template parameters: [...] However, that only works with identifiers.The general-case replacement for this is a string mixin: ```d string myAssert(string condition, string message = "assertion failed: ") { return `assert(` ~ condition ~ `, q"(` ~ message ~ condition ~ `)");`; } void main() { mixin(myAssert("2 + 2 == 5")); } ```
Jul 18 2023