int nan
Ary Borenszweig
ary at esperanto.org.ar
Sun Jun 28 09:10:51 PDT 2009
Michiel Helvensteijn escribió:
> Nick Sabalausky wrote:
>
>>> Yes, this approach is what I was getting at. In fact, I would (and
>>> already have in the past) argue that this is *better* than the "holy
>>> grail" approach, because because it's based on very simple and easy to
>>> remember rules. Conversely, the "holy grail" approach leads to
>>> difficult-to-predict cases of small, seemingly-innocent changes in one
>>> place causing some other code to suddenly switch back and forth between
>>> "compiles" and "doesn't compile". Take this modified version of your
>>> example:
>>>
>>> ------------
>>> // Imagine foo resides in a completely different package
>>> int foo() { return 5; }
>>>
>>> int i;
>>> for(int j = foo(); j > 3; j--) i = j;
>>> auto k = i; // Compiles at the moment...
>>> ------------
>>>
>>> Now make a perfectly acceptable-looking change to foo:
>>> ------------
>>> int foo() { return 2; }
>>> ------------
>>>
>>> And all of a sudden non-local code starts flip-flopping between
>>> "compiles" and "doesn't compile".
>
> Better than a flipflop between "runs correctly" and "runs incorrectly",
> wouldn't you agree? But of course, you're arguing on the other end of the
> spectrum. Read on.
>
>>> Additionally, even the "holy grail" approach still has to reduce itself
>>> to being overly conservative in certain cases anyway:
>>> ------------
>>> int foo()
>>> {
>>> auto rnd = new RandomGenerator();
>>> rnd.seed(systemClock);
>>> return rnd.fromRange(1,10);
>>> }
>>> ------------
>
> I wouldn't call the "holy grail" overly conservative in this instance. The
> post-condition of 'foo' would simply be (1 <= returnValue <= 10). With no
> more information than that, the compiler would have to give an error,
> since 'foo' *may return a value* that results in an uninitialized read
> of 'i'. That's how it should work. No errors if and only if there is no
> possible execution path that results in failure, be it uninitialized-read
> failure, null-dereference failure or divide-by-zero failure.
>
>>> So, we only have two initial choices:
>>> - Overly conservative (C#-style or "holy grail")
>>> - Overly permissive (current D approach)
>
> I tend to agree with BCS that the programmer should have the last say,
> unless the compiler can absolutely prove that (s)he is wrong. Given the
> choice between overly conservative and overly permissive, I would pick
> overly permissive.
>
> But the beauty of the holy grail is that it's neither.
>
>> Additionally, in the C# approach (and this is speaking from personal
>> experience), anytime you do come across a provably-correct case that the
>> compiler rejects, not only is it always obvious to see why the compiler
>> rejected it, but it's also trivially easy to fix. So in practice, it's
>> really not much of a "baby with the bathwater" situation at all.
>
> But what would the fix be in the case of our example? Surely you're not
> suggesting initializing 'i' to 0? Then we'd be back in the old situation
> where we might get unexpected runtime behavior if we were wrong
> about 'foo'.
>
> An acceptable solution would be:
>
> int i;
> assert(foo() > 3);
> for(int j = foo(); j > 3; j--) i = j;
> auto k = i; // Compiles at the moment...
>
> Would C# swallow that?
Of course not:
int foo() {
return rand() % 10;
}
More information about the Digitalmars-d
mailing list