May I introduce `lazy with`?
Quirin Schroll
qs.il.paperinik at gmail.com
Thu Nov 24 17:41:20 UTC 2022
[Enhancement issue
23503](https://issues.dlang.org/show_bug.cgi?id=23503)
In the discussion thread for DIP 1044, because Walter suggested
adding an implicit `with (typeof(expr))` to `switch (expr)`, it
occurred to me that `with` has an issue that makes it unsuitable
for certain use-cases, including generic code, and that issue can
be solved.
The essence of the problem is that `with (TypeOrExpr)` will
prefer resolving an identifier `id` as `TypeOrExpr.id` whenever
`TypeOrExpr.id` is viable:
```d
with (EnumType)
switch (enumValue)
{
static foreach (member; EnumMembers!EnumType)
{
case member: // What if EnumType has a member named
`member`?
...;
}
}
```
When `EnumType` happens to have a member named `member`, `with`
will greedily take it and the loop will produce nonsense.
What would be useful here is a version of `with` that only
resolves `id` as `TypeOrExpr.id` whenever `id` is not otherwise
resolvable, i.e. as a last resort.
I’d suggest using `lazy with` for that construct. It is otherwise
exactly like `with`. Its advantage is that it can be used in
generic code and thus be implicitly added.
Were the `with` statement above a `lazy with`, the identifier
`member` would always resolve to the `foreach` iteration.
Following Walter’s suggestion, a `lazy with` can be added
implicitly to `switch` statements and declarations with
spelled-out type:
```d
EnumType e = enumMember;
// as if `EnumType e = EnumType.enumMember`, unless `enumMember`
is in scope
int x = max - 1; // as if `int x = int.max - 1`, unless another
`max` is in scope.
double myEps = 2 * epsilon; // as if `= 2 * double.epsilon`,
unless...
```
Note that `with (int)` currently does not work.
What do you think?
More information about the Digitalmars-d
mailing list