Regan Heath:

That's a matter of opinion. I like to see null checks at the top of a function or method, it makes it far more likely to be safe and it means I can ignore the possibility of null from then on - making the code much cleaner.

Even more clear/short/light is to not need such checks, and take arguments with a light tagging syntax that assures them to be not null.

Compare:

void foo1(C1 c1, C2 c2)
in {
    assert(c1 !is null);
    assert(c2 !is null);
} body {
    ...
}


With:

void foo2(C1@ c1, C2@ c2) {
    ...
}


There the @ suffix means not-nullable, it's a D2-compatible syntax. In a better designed language, you do the opposite, adding ? for nullable reference/pointers, so it becomes (both can't be null):

void foo3(C1 c1, C2 c2) {
    ...
}


Doing this moves the burden of verifying not-nullness out of foo2/foo3. If the argument of foo is given to many functions, you don't have to test c1 and c2 in every function, saving lines of code, space, run-time and avoiding mistakes (and null-related bugs are not uncommon).

To create a not-null variable you have to create it assigning it to something that is not null (this is the most common case), or you have to test it. This test for not-null is similar to the tests inside foo1. But such tests tend to be closer to where problems are.

A well implemented not-null system asks you to test nullables before dereferencing, and keeps track of the nullable/notnull type state inside the if statement clauses, avoiding useless tests (this means that if you test for null a nullable, inside the else clause the state of its type is not-null).

Bye,
bearophile

Reply via email to