Wanted: best way to express default expectations

Dukc ajieskola at gmail.com
Thu Oct 10 11:34:44 UTC 2019


This is a very common pattern:

```
auto sumSquares(R)(R values)
     if (isInputRange!R && isPointer!(ElementType!R) && 
isIntegral!(typeof(*values.front)))
{   typeof(*values.front) result = 0;
     foreach (value; values)
     {	if (value is null) continue;
      	result += *value * *value;
     }
     return result;
}
```

`values` may obviously contain null values, which have to be 
taken account in the body of the `foreach` loop.

The problem here is that `if (value is null)` is stating the 
condition rest of the code block does NOT want. This is exactly 
the opposite behaviour of `assert`, `enforce` and `in` 
statements, and will make - I think - maintenance-induced bugs 
more likely.

You can't just add a library solution in conventional D style, 
because a lambda you would pass to `alias` template parameter 
could not `continue` the foreach loop (nor `return`, `break` or 
`goto`).

a '!' mark to negate the `if` condition works, but at least for 
my eye, it would be more cognitive load to read such a condition, 
especially if it has and/or statements that have to be negated as 
whole.

In this case, the best solution would doubtlessly be this:
```
foreach (value; values) if (value !is null)
{   result += *value * *value;
}
```

...however this is a bad general solution. Often, you have many 
expectations that must be stated at different parts of the code 
block. This solution to those cases would mean very deep nesting, 
and a lot of short `else` statements at the end of the function. 
Not ideal.

Perhaps the best general solution I can come up with is `if 
(value !is null){} else continue`. It states the default 
expectation instead of it's negation value, and handles the 
exceptional case right away. Still, quickly looking, it looks a 
lot like of an `if` statement that is meant to branch the code 
block, not just terminate it early, and thus i think the negation 
(`{} else`) might be missed more easily than with e.g. `assert`s.

Note that this does not only apply to loops. It's just as common 
to shortcut-return from a function in cases where rest of the 
logic is needless.

What do you think? Is there a good possiblility to do some sort 
of library solution? Or would a DIP be more appropriate? Or is my 
taste just a bit strange here?


More information about the Digitalmars-d mailing list