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








Paul Backus <snarwin gmail.com>