Fixing C's Biggest Mistake

Sebastiaan Koppe mail at skoppe.eu
Sun Jan 1 15:24:26 UTC 2023


On Sunday, 1 January 2023 at 01:58:18 UTC, Walter Bright wrote:
> On 12/30/2022 11:55 PM, Sebastiaan Koppe wrote:
>> In a larger program the first one allows the programmer to do 
>> the check once and rely on it for the remainder of the program.
>
> Which is what usually happens with nullable pointers. We check 
> once and rely on it to be non-null for the rest of the program

Oh but here is the difference, with nonnull pointers its the type 
system that keeps me honest and in your case its another 
responsibility for the programmer.

>> Essentially it leverages the type system to make invalid state 
>> unrepresentable.
>
> I actually do understand that, I really do. I'm pointing out 
> that the hardware makes dereferencing null pointers impossible. 
> Different approach, but with the same end result.

Valuable software is forever in a state of change; a series of 
additions, refactorings, removals etc. To make those changes 
easier it helps if you limit the assumptions each line of code 
has. Things like: "This dereference on line 293 is fine because 
we checked it at line 237" make refactorings harder. In order to 
keep high plasticity you want to limit these implicit - invisible 
- connections.

Having unittests helps fearless refactoring. Using the type 
system to your advantage helps a lot too.

>> This simplifies subsequent code.
>
> I'm not so sure it does. It requires two types rather than one 
> - one with the possibility of a null, one without. Even the 
> pattern matching to convert the type is more work than:
>
>    if (p) ...

Yes, it is a little bit more work, but that often happens 
somewhere on the boundary of the (sub)program, so that the 
remainder can just work with the more restricted type.

Also, somewhat tangentially related, isn't nonnull-ness one of 
the things `ref` helps with:

```dlang
// transmogrifies `p`, `p` must be non-null!
void transmogrify1(int* p);
// transmogrifies `p`
void transmogrify2(ref int p);
```

`transmogrify2` uses the type system to express its non-null 
requirement, which anyone can see just glancing at the signature. 
That is worth something.

> Personally, I'm most interested in sumtypes and pattern 
> matching as a better error handling mechanism than throwing 
> exceptions.

Very happy to hear that. I recently wrote 
https://github.com/skoppe/oras/blob/master/source/oras/client.d 
which uses mir's algebraics to make all the possible errors 
explicit. On top of that it uses `nothrow` to make sure no 
exceptions slip in due to changes.


More information about the Digitalmars-d mailing list