April 21, 2012 Re: Docs: Section on local variables | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | "Jonathan M Davis" <jmdavisProg@gmx.com> wrote in message news:mailman.2003.1334971962.4860.digitalmars-d@puremagic.com... > On Saturday, April 21, 2012 02:54:25 Jakob Ovrum wrote: >> On Friday, 20 April 2012 at 18:40:46 UTC, Jonathan M Davis wrote: >> > But there's no way that the compiler is going to enforce >> > that, and if it did, it would require that you initialize the >> > variable in the >> > above example even though the compiler already does. >> >> Why can't the compiler enforce it? C# and Java compilers can do it just fine. > > I didn't say that it couldn't. I said that there was no way that it would. > It > would break a lot of code, and it goes completely against D's current > approach > of default-initialization everything. I'd be shocked if Walter agreed to > making the compiler give an error for variables which aren't either > assigned > to or directly initialized before they're used. init solves the problem > already. There's no need to do what C# and Java do on top of that. > I agree that it's never going to happen in D, and I can even live with that. However, .init definitely does *NOT* solve the problem. The problem is "variables being read before they're properly initialized". The .init value is NOT ALWAYS the proper initialization value. We *all* know that: that's why we *have* initializer syntax. I'm not going to try to argue for D to start doing C#-style initialization checks. That ship has unfortunately sailed. But we need to put a stop to this absurd myth that .init "solves the problem". It doesn't do a damn thing more to solve the problem than what "indent scoping" does to solve "improper indentation" - it takes a catchable programmer error, replaces it with a subtle bug, and exclaims "Fixed! See, no more error!". | |||
April 21, 2012 Re: Docs: Section on local variables | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Nick Sabalausky | On Saturday, April 21, 2012 01:38:22 Nick Sabalausky wrote:
> "Jonathan M Davis" <jmdavisProg@gmx.com> wrote in message news:mailman.2003.1334971962.4860.digitalmars-d@puremagic.com...
>
> > On Saturday, April 21, 2012 02:54:25 Jakob Ovrum wrote:
> >> On Friday, 20 April 2012 at 18:40:46 UTC, Jonathan M Davis wrote:
> >> > But there's no way that the compiler is going to enforce
> >> > that, and if it did, it would require that you initialize the
> >> > variable in the
> >> > above example even though the compiler already does.
> >>
> >> Why can't the compiler enforce it? C# and Java compilers can do it just fine.
> >
> > I didn't say that it couldn't. I said that there was no way that it would.
> > It
> > would break a lot of code, and it goes completely against D's current
> > approach
> > of default-initialization everything. I'd be shocked if Walter agreed to
> > making the compiler give an error for variables which aren't either
> > assigned
> > to or directly initialized before they're used. init solves the problem
> > already. There's no need to do what C# and Java do on top of that.
>
> I agree that it's never going to happen in D, and I can even live with that.
>
> However, .init definitely does *NOT* solve the problem. The problem is "variables being read before they're properly initialized". The .init value is NOT ALWAYS the proper initialization value. We *all* know that: that's why we *have* initializer syntax.
>
> I'm not going to try to argue for D to start doing C#-style initialization checks. That ship has unfortunately sailed. But we need to put a stop to this absurd myth that .init "solves the problem". It doesn't do a damn thing more to solve the problem than what "indent scoping" does to solve "improper indentation" - it takes a catchable programmer error, replaces it with a subtle bug, and exclaims "Fixed! See, no more error!".
init solves the larger problem of uninitialized variables being garbage and resulting in non-deterministic behavior. And it solves it in more places than the Java and C# solution does, because it deals with stuff like initializing all of the elements in an array when it's first allocated, which they don't AFAIK.
True, init doesn't make it so that programmers always remember to initialize all of their variables, and with a default-initialized variable, you have the ambiguity of whether the programmer meant to use the default or whether they forgot to initialize the variable, but that's minor in comparison to uniitialized variables being garbage values. And since there's nothing to stop a programmer from initializing a variable with an incorrect value, the fact that a variable is directly initialized by the programmer in Java and C# doesn't necessarily solve that problem any better anyway. And then there's also the irritation of the occasional forced initialization, because the compiler's flow analysis isn't good enough to detect that it's unecessary.
So, it's highly debatable whether Java and C#'s solution would be an improvement over init or whether having it in addition to init would be desirable, but regardless of whether either solves the issue of programmers not initializing variables to correct values, init definitely solves the problem of having garbage for uninitialized variables like you do in C/C++. And _that_ is what _needs_ to be solved.
- jonathan M Davis
| |||
April 21, 2012 Re: Docs: Section on local variables | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jakob Ovrum | On Saturday, April 21, 2012 03:53:08 Jakob Ovrum wrote:
> On Saturday, 21 April 2012 at 01:31:45 UTC, Jonathan M Davis
> >_Very_ little in D requires or does flow
> > analysis.
>
> And D is worse off because of it.
Not being a compiler expert, I don't really know how much an issue flow analysis really is, but for better or worse, Walter clearly thinks that it complicates the compiler unnecessarily. Still, there are at least optimization cases where it would probably help quite a bit to be able to do more flow analysis. So, I do agree on that level. However, in this particular case, I don't think that Java and C#'s solution for forced initialization of variables prior to usage really buys us anything.
- Jonathan M Davis
| |||
April 21, 2012 Re: Docs: Section on local variables | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | "Jonathan M Davis" <jmdavisProg@gmx.com> wrote in message news:mailman.2009.1334999769.4860.digitalmars-d@puremagic.com... > On Saturday, April 21, 2012 01:38:22 Nick Sabalausky wrote: >> "Jonathan M Davis" <jmdavisProg@gmx.com> wrote in message news:mailman.2003.1334971962.4860.digitalmars-d@puremagic.com... >> >> > On Saturday, April 21, 2012 02:54:25 Jakob Ovrum wrote: >> >> On Friday, 20 April 2012 at 18:40:46 UTC, Jonathan M Davis wrote: >> >> > But there's no way that the compiler is going to enforce >> >> > that, and if it did, it would require that you initialize the >> >> > variable in the >> >> > above example even though the compiler already does. >> >> >> >> Why can't the compiler enforce it? C# and Java compilers can do it just fine. >> > >> > I didn't say that it couldn't. I said that there was no way that it >> > would. >> > It >> > would break a lot of code, and it goes completely against D's current >> > approach >> > of default-initialization everything. I'd be shocked if Walter agreed >> > to >> > making the compiler give an error for variables which aren't either >> > assigned >> > to or directly initialized before they're used. init solves the problem >> > already. There's no need to do what C# and Java do on top of that. >> >> I agree that it's never going to happen in D, and I can even live with that. >> >> However, .init definitely does *NOT* solve the problem. The problem is >> "variables being read before they're properly initialized". The .init >> value >> is NOT ALWAYS the proper initialization value. We *all* know that: that's >> why we *have* initializer syntax. >> >> I'm not going to try to argue for D to start doing C#-style >> initialization >> checks. That ship has unfortunately sailed. But we need to put a stop to >> this absurd myth that .init "solves the problem". It doesn't do a damn >> thing >> more to solve the problem than what "indent scoping" does to solve >> "improper indentation" - it takes a catchable programmer error, replaces >> it >> with a subtle bug, and exclaims "Fixed! See, no more error!". > > init solves the larger problem of uninitialized variables being garbage > and > resulting in non-deterministic behavior. And it solves it in more places > than > the Java and C# solution does, because it deals with stuff like > initializing > all of the elements in an array when it's first allocated, which they > don't > AFAIK. > > True, init doesn't make it so that programmers always remember to > initialize > all of their variables, and with a default-initialized variable, you have > the > ambiguity of whether the programmer meant to use the default or whether > they > forgot to initialize the variable, but that's minor in comparison to > uniitialized variables being garbage values. And since there's nothing to > stop > a programmer from initializing a variable with an incorrect value, the > fact > that a variable is directly initialized by the programmer in Java and C# > doesn't necessarily solve that problem any better anyway. And then there's > also the irritation of the occasional forced initialization, because the > compiler's flow analysis isn't good enough to detect that it's unecessary. > > So, it's highly debatable whether Java and C#'s solution would be an > improvement over init or whether having it in addition to init would be > desirable, but regardless of whether either solves the issue of > programmers > not initializing variables to correct values, init definitely solves the > problem of having garbage for uninitialized variables like you do in > C/C++. > And _that_ is what _needs_ to be solved. > "And _that_ is what _needs_ to be solved." <--- Strawman. The garbage values issue is nothing more than C/C++ going a stupid route. It's not a problem to be solved - it's merely a C/C++ "WAT" that is to simply *not be imitated*. Every other (relevent) language in existance (as far as I'm aware) avoids copying that broken design. Score: C/C++: Zero. Everything else: One. You can frame that as "a problem to be solved", fine. But there it is. It's solved. In both D and C# and everywhere but C/C++. Done. End of *that* story. But now, C#, as well as some other langauges, *also* have guards against forgetting to initialize a variable to it's *intended* initial value. D does *not* guard against this, period. C/C++: Fails to solve A and B: Big fat Zero D: Solves A, fails to solve B: One C#: Solves A and B: Two D's .init doesn't even enter into this. D's .init doesn't solve a damn thing here. It solved the *other* problem - it's not relevent to *this* problem. C# has solved an *additional* issue *beyond* what D (and everything else) solves. You make it sound like .init is a "different but equal" approach. It isn't. It solves one problem, whereas C# solves two. As far as "there's nothing to stop a programmer from initializing a variable with an incorrect value": that's a poor argument. Failing to give an initial value in all code paths is a bigger danger (ie, more likely) than using the wrong value. That's because if you're initializing it *at all*, you're already *at least* thinking about it, which gives you a huge advantage. On top of that, while explicitly initing to the wrong value isn't catchable by the compiler anyway, failing to explicitly init at all *is* catchable (which therefore *forces* the programmer to put at least *some* thought into it, thus *decreasing* the likelyhood of the wrong value as compared to D). Furthermore, Walter has argued that people would just toss values in to shut it up whithout any regard to whether or not it's right. Fact is, in real world practice, and this is coming from someone who has actually *used* C#, and not merely speculated about it: that's *not* what typically happens in real-world C#. But again, I know D's never going to change in this regard, and I can even live with that. But it *is*, *objectively*, a downside of D versus C#. Disputing that with "But D gets rid of garbage initial values!" is nothing but an irrelevant strawman. | |||
April 21, 2012 Re: Docs: Section on local variables | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Nick Sabalausky | Nick Sabalausky:
> But it *is*, *objectively*, a downside of D versus C#.
> Disputing that with "But D gets rid of garbage initial values!" is nothing but an irrelevant strawman.
This is right, and D people seem to forget it often. So I think we'll have to keep reminding this fact forever to D programmers/designers, in D.learn too.
Bye,
bearophile
| |||
April 21, 2012 Re: Docs: Section on local variables | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Nick Sabalausky | On Saturday, 21 April 2012 at 11:37:29 UTC, Nick Sabalausky wrote: > As far as "there's nothing to stop a programmer from initializing a variable > with an incorrect value": that's a poor argument. Failing to give an initial > value in all code paths is a bigger danger (ie, more likely) than using the > wrong value. That's because if you're initializing it *at all*, you're > already *at least* thinking about it, which gives you a huge advantage. On > top of that, while explicitly initing to the wrong value isn't catchable by > the compiler anyway, failing to explicitly init at all *is* catchable (which > therefore *forces* the programmer to put at least *some* thought into it, > thus *decreasing* the likelyhood of the wrong value as compared to D). I agree, it's much easier to spot an incorrect explicit initializer than code unintentionally relying on an implicit default-initializer. > Furthermore, Walter has argued that people would just toss values in to shut > it up whithout any regard to whether or not it's right. Fact is, in real > world practice, and this is coming from someone who has actually *used* C#, > and not merely speculated about it: that's *not* what typically happens in > real-world C#. I've used C# a fair bit too, and this has never even happened to me (not in Java either using Eclipse). Of course, this is just a personal anecdote, but if anyone has had problems with the CFG approach in these languages, I'd like to hear more about it. As it stands the claim that people would be tossing in half-assed explicit initializers all the time is simply not the reality. Even if the compiler gets it wrong once in a blue moon, I would happily trade that for the massive benefits it gives you in writing readable, maintainable code. I don't think this ship has sailed for D. If it were to be implemented, you could easily transition into it slowly like @property. Also, the same implementation could be used to solve the problem of statically checking when const/immutable constructors are cooked/baked, which remains an unsolved problem. | |||
April 21, 2012 Re: Docs: Section on local variables | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Nick Sabalausky | Even if my words count for little: 1. If it would be possible to reliably detect reading access to not explicitly initalized variables the best solution would be to forbid reading access before initialization and throw an error message. (Particularly, in this world, there would be no default initialization.) 2. Unfortunately, it seems as if there are situations where it is not (actually or virtually) possible to decide whether a variable is initialized. This means an error message can be thrown only if the compiler can surely decide whether a variable is initialized. Otherwise, a warning could be given. In practice, of course, this could lead to a flood of warning messages (some of which will be false positives). 3. In presence of default initialization, it is impossible to read uninitialized variables. That's it? To me, this sounds a bit too easy. Often, the default value is not what we want. If the default value is what we want then we have two possibilities: * rely on default initialization, * do explicit initialization. If we find a defintion without explicit initialization it is unclear whether the author intended to rely on default initialization. Practically, it seems to be good style, not to rely on default initialization at all but explicitly initialize all variables. This requires discipline. Effectively, default initialization does not help a disciplined programmer at all. On the other hand, it does not hurt a disciplined programmer. :-P It would certainly ease life of a developer if warnings about (a) surely, (b) possibly not explicitly initialized variables could be emitted optionally. For disciplined programmers, errors of type (a) would be even more desirable. | |||
April 21, 2012 Re: Docs: Section on local variables | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On Saturday, 21 April 2012 at 09:15:14 UTC, Jonathan M Davis wrote:
> the Java and C# solution does, because it deals with stuff like initializing
> all of the elements in an array when it's first allocated, which they don't
> AFAIK.
They do.
| |||
April 21, 2012 Re: Docs: Section on local variables | ||||
|---|---|---|---|---|
| ||||
On Sat, Apr 21, 2012 at 02:14:14AM -0700, Jonathan M Davis wrote: > On Saturday, April 21, 2012 01:38:22 Nick Sabalausky wrote: > > "Jonathan M Davis" <jmdavisProg@gmx.com> wrote in message news:mailman.2003.1334971962.4860.digitalmars-d@puremagic.com... [...] > > > I didn't say that it couldn't. I said that there was no way that it would. It would break a lot of code, and it goes completely against D's current approach of default-initialization everything. I'd be shocked if Walter agreed to making the compiler give an error for variables which aren't either assigned to or directly initialized before they're used. init solves the problem already. There's no need to do what C# and Java do on top of that. > > > > I agree that it's never going to happen in D, and I can even live with that. > > > > However, .init definitely does *NOT* solve the problem. The problem is "variables being read before they're properly initialized". The .init value is NOT ALWAYS the proper initialization value. We *all* know that: that's why we *have* initializer syntax. > > > > I'm not going to try to argue for D to start doing C#-style initialization checks. That ship has unfortunately sailed. But we need to put a stop to this absurd myth that .init "solves the problem". It doesn't do a damn thing more to solve the problem than what "indent scoping" does to solve "improper indentation" - it takes a catchable programmer error, replaces it with a subtle bug, and exclaims "Fixed! See, no more error!". > > init solves the larger problem of uninitialized variables being garbage and resulting in non-deterministic behavior. And it solves it in more places than the Java and C# solution does, because it deals with stuff like initializing all of the elements in an array when it's first allocated, which they don't AFAIK. > > True, init doesn't make it so that programmers always remember to initialize all of their variables, and with a default-initialized variable, you have the ambiguity of whether the programmer meant to use the default or whether they forgot to initialize the variable, but that's minor in comparison to uniitialized variables being garbage values. And since there's nothing to stop a programmer from initializing a variable with an incorrect value, the fact that a variable is directly initialized by the programmer in Java and C# doesn't necessarily solve that problem any better anyway. And then there's also the irritation of the occasional forced initialization, because the compiler's flow analysis isn't good enough to detect that it's unecessary. [...] Hold on a second here, I thought the original complaint was that *unused* local variables should generate a warning? What has that got to do with .init? If I write code like this: void func() { int x; int y; return y+10; } Then x is unused, regardless of whether the language defaults its value to .init or not. I can understand why Walter doesn't care to implement the necessary flow analysis to catch these sorts of problems, but it shouldn't be confused with variable initialization, because they are orthogonal issues. I mean, the above code could just as easily be written: void func() { int x = 123; int y; return y+10; } and x is *still* an unused variable (in the sense that the code doesn't do anything with it after assigning an initial value). T -- "You are a very disagreeable person." "NO." | ||||
April 21, 2012 Re: Docs: Section on local variables | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Nick Sabalausky | On 4/21/12, Nick Sabalausky <SeeWebsiteToContactMe@semitwist.com> wrote: > Yes, it's initialized to .init by default. But .init may not be what the programmer intended it to be initialized to. Well, we could introduce a new language feature that explicitly makes the compiler verify that you've initialized a variable before using it. This could help in cases where e.g. you have static if sections and you forget to add an else clause: string name = none; // 'none' would be a sentinel for the compiler enum i = 2; static if (i == 1) { name = ...; } // forgotten else clause if (name == ...) { } // compile-time error This way we don't interrupt existing code that relies on .init. Either we introduce some new syntax for initializers, or we get customized warning options. Personally I prefer the latter, but unfortunately Walter went full-on Steve Jobs on compiler options for some reason. Also take note of this case: int[string] hash; ... int x = hash.get("foo", 0); I think this is perfectly legal code that shouldn't be worthy of a warning. But how can the compiler know not to emit a warning here? | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply