Getting code in strings: __EXPRESSION_OF__
Quirin Schroll
qs.il.paperinik at gmail.com
Tue Jul 18 13:33:49 UTC 2023
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.
More information about the Digitalmars-d
mailing list