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:
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:
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?