On Sun, 25 Dec 2011 00:09:08 +1100, bearophile <[email protected]> wrote:

Derek Parnell:

In my code such mistakes are uncommon.

But not impossible.

Designing an engineering system like a programming language is often a matter of trade-offs. If in my code I find a problem (like integer overflows) quite more common than other ones (like bugs caused by implicit bool->int conversions) it is very right for me to desire the first ones issued first. Priorities are really important in engineering.

I agree that priorities are extremely important. However, I'm not seeing that this bool->int conversion is an either-or situation. We are not being forced to choose between integer overflow issues and bool->int conversion issues. Our code should, right now, cater for both issues as it is not really a great deal of work to write code that deals with both.

I believe that casts often "shut up the compiler" but I don't belive that's their purpose. One of their main purposes is to offer a standard way to break the static type system in specific points of the program. Every type system restricts the number of the acceptable programs. But programmers sometimes want to write some of those programs. To do this they sometimes use casts. D casts have other secondary purposes, like bit reinterpretation, etc.

Yes, 'cast' is a poor choice of word here. Sometimes we need to tell the compiler to do a data conversion (transforming bits into a new format) and sometimes we need to tell it to assume that the bits are already in the correct format even though it would not otherwise agree with you.

One issue you have highlighted below is that 'cast(T)' is not exactly totally explicit. The coder cannot simply tell if it is doing a data conversion or a data re-interpretation. That requires some background knowledge about D's internals. Furthermore, when doing a data conversion, the 'cast(T)' syntax is only explicit about the target format; it implies the source format from the datatype of its operand. And as you point out below, that can be a source of bugs.

In practice my experience shows that the programmer (me too) sometimes
doesn't have perfect knowledge (usually because the code later was
modified, turning the cast into a bug because casts are often silent).

You realize that the exact argument can be made about implicit casts.

You are missing something important. Currently this code compiles, it performs a silent implicit cast:

bool foo() { return true; }
void main() {
    int x = foo();
}


Now you change the code, foo returns a double, the implicit cast stops being accepted and the compiler gives an error:

double foo() { return 1.5; }
void main() {
    int x = foo();
}


The same doesn't happen if you use an explicit cast. This is the original code if we now require a cast to assign a bool to an int:

bool foo() { return true; }
void main() {
    int x = cast(int)foo();
}


Now if you modify the code, so foo returns a double, the cast keeps silencing the compiler and this is a possible bug that goes unnoticed (you lose information doing double->int, while bit->int doesn't lose information):


double foo() { return 1.5; }
void main() {
    int x = cast(int)foo();
}


Yes, I agree that this is a potential source of bugs. So what we need is something more explicit.

 double foo() { return 1.5; }
 void main() {
     int x = cast(double:int)foo();
 }

Now the code is very clear about your intentions for it, and if foo() is later modified to return some incompatible datatype, the compile can alert the coder.

And to be consistent, we need to have syntax that allows a coder to explicitly tell the compiler to do a re-interpretation cast.

--
Derek Parnell
Melbourne, Australia

Reply via email to