Final lecture by Andrei Alexandrescu.
A simple pattern that can be expressed in many languages. We want to perform an action, a second action and if the second action fails, we need to perform a rollback and in any case, we need a cleanup. This can be done with a try-catch. However, if you want to combine 2 sets of actions, we need a nested try-catch and this is not very beautiful.
Andrei’s conclusion is that dislocation + nesting = fail.
“Error handling is about maintaining invariant, and only incidentally about handling the error itself”
So how does D does this?
With this, we can just compose the action, they do not need to be mixed in the code. But note that only the code is linear, the flow of control is not. It is transformed into nested try-catches that you don’t want to write. This resulted in a 2-5 times improvements of relevant metrics (like lines of code)
Many system languages do not support arrays, since they can be created with pointers. But the problem with pointers is that they are unsafe, but efficient. In D there is a built-in very lightweight abstraction for arrays, just consisting of a pointer + the length. With this, you obtain safety for iteration and indexing.
Value Range Propagation
D has many different type of ints, but how to determine the type of a arithmic operation? In C, default is an int, unless in is a long, plus some extra rules specifically for unsigned. long to char is implicit. In C# and Jave, you need to cast.
All these option from other languages have downsides.
In compilers, there is Value Range Propagation: for variables, the min/max values of intermediate calculations are stored, so casts are not necessary.