digitalmars.D - null [re: spec#]
- foobar (11/11) Nov 06 2010 1. the INVENTOR of the "reference" concept himself admits that this is a...
- bearophile (5/6) Nov 06 2010 Discussing this is a waste of time now, this part of the D language will...
- foobar (8/17) Nov 06 2010 I haven't discussed syntax at all so to make clear:
- retard (2/6) Nov 06 2010 Then why are you here?
- foobar (2/10) Nov 06 2010 You just proved your nickname by quoting me out of context.
- so (12/34) Nov 07 2010 Fine having a nun-null type or ranged integer or special float whatever ...
- bearophile (4/7) Nov 07 2010 There's no way you may implement all the relative semantics in the D lan...
- Andrei Alexandrescu (4/11) Nov 07 2010 What's a relative semantics? And what was exactly the claim that was wro...
- bearophile (9/11) Nov 07 2010 - The limited form of typestate change, as shown in the original Spec# p...
- so (5/13) Nov 07 2010 You are saying as it is something trivial. :)
- bearophile (4/7) Nov 07 2010 Sorry, I didn't mean to sound like that. It's indeed hard to design the ...
- Andrei Alexandrescu (10/19) Nov 07 2010 The only change needed is constructor flow to make sure types with
- Simen kjaeraas (5/15) Nov 08 2010 One more thing: structs with NotNull!T fields will need to have their
- Jonathan M Davis (18/32) Nov 08 2010 ??? Structs have no default constructor. They have an init property with...
- Simen kjaeraas (28/39) Nov 08 2010 True. Disabling the default constructor here means that
- Jonathan M Davis (27/50) Nov 08 2010 I was not aware of that. I didn't think that you could do that for struc...
- Walter Bright (13/30) Nov 08 2010 That's right.
- Jonathan M Davis (9/32) Nov 08 2010 How hard would it really be to insert code wherever a struct's init valu...
- Walter Bright (5/12) Nov 08 2010 There are some severe problems with that approach. One of the largest is...
- dsimcha (5/17) Nov 08 2010 While I'm also skeptical of the idea that simply declaring a variable ca...
- Walter Bright (3/7) Nov 08 2010 Not a bad idea, but this still leaves people nowhere who need non-trivia...
- Jonathan M Davis (15/24) Nov 08 2010 Well, if it's a default constructer which has to be nothrow and maybe pu...
- Walter Bright (4/17) Nov 08 2010 Actually, you do as init takes care of most of the initializations, and ...
- Jonathan M Davis (17/37) Nov 08 2010 We definitely want to avoid the nastier issues, but the lack of default
- Simen kjaeraas (11/24) Nov 09 2010 In my experience, disabling the default constructor would be enough.
- Jonathan M Davis (13/37) Nov 09 2010 Except that I _want_ to have default constructors for structs. Sure, hav...
- Simen kjaeraas (22/46) Nov 08 2010 Indeed. That's been discussed here, and in short, these are the rules:
- steveh (3/9) Nov 06 2010 I've known there are hidden tradeoffs when using these 'intelligent' typ...
- Simen kjaeraas (10/15) Nov 06 2010 And here you are sorely mistaken. The point of non-nullable types is the
- bearophile (11/19) Nov 06 2010 This is not true. They may "add" some runtime checks, but in practice yo...
- =?UTF-8?B?IkrDqXLDtG1lIE0uIEJlcmdlciI=?= (35/37) Nov 06 2010 No they don't. They *remove* runtime checks everywhere.
- Eric Poggel (5/11) Nov 07 2010 I still live in D1 land, so forgive me if I'm out of the loop--but what
- Simen kjaeraas (11/27) Nov 08 2010 NotNull!T needs to have its default constructor disabled. That is the #1
- Denis Koroskin (13/39) Nov 08 2010 Not exactly disabled. The following should work:
- Simen kjaeraas (9/52) Nov 08 2010 I belive you have misunderstood me. The NonNull struct would need to hav...
- bearophile (4/6) Nov 08 2010 It's time to update those goals.
- steveh (5/11) Nov 08 2010 I studied the situation further. Now I've decided to leave D. I tried to...
- foobar (5/21) Nov 08 2010 Your conclusion that less types = better is patently incorrect.
- bearophile (5/7) Nov 08 2010 In practice on average my small Python programs are less buggy than my s...
- Walter Bright (5/6) Nov 08 2010 One's experience with a particular language can have a very strong influ...
- dennis luehring (4/5) Nov 08 2010 sounds good, but strong typesystem pissed poeple normaly don't tend to
- Manfred_Nowak (4/5) Nov 08 2010 Then no types are best?
- so (6/19) Nov 08 2010 Your choice is perfectly reasonable, you use static typed languages
- Bruno Medeiros (11/21) Nov 25 2010 I'm often hearing that argument from the new dynamic languages crowd:
- spir (41/43) Nov 25 2010 I tried to find some light on this topic a while ago, because similar ar...
- Nick Sabalausky (20/39) Nov 06 2010 First of all, "appeal to authority" is a logical fallacy. Second, there ...
- Jonathan M Davis (36/53) Nov 06 2010 Well, it _is_ better than C. Going C# or Java's route forces the program...
- Walter Bright (30/33) Nov 06 2010 Correct. It's not that doing flow analysis is hard, it's that it's impos...
- Nick Sabalausky (49/83) Nov 06 2010 Since when should crap like that ever be written in the first place? In ...
- Nick Sabalausky (9/97) Nov 06 2010 Additionally, the root problem with default values is that they make
- retard (7/121) Nov 07 2010 When I started with D, some of the main reasons for choosing D were:
- Roman Ivanov (45/83) Nov 07 2010 I know what your mean, but the example is flawed:
- Roman Ivanov (3/99) Nov 07 2010 OF course, the code above assumes that Duck is unnulable. I didn't want
- Simen kjaeraas (17/35) Nov 07 2010 You misunderstand. The idea is this:
- Nick Sabalausky (40/62) Nov 07 2010 If you do that, then there's two possibilities:
- Simen kjaeraas (13/33) Nov 07 2010 There is a third option, wherein the if condition will only be true if
- Nick Sabalausky (5/39) Nov 07 2010 - if ( m > 12 ) {
- Simen kjaeraas (5/9) Nov 07 2010 Of course. But the point is, this is unnecessary. We know p !is null
- Nick Sabalausky (6/14) Nov 07 2010 And my point is, the need to write it the way you described is unnecessa...
- Walter Bright (21/34) Nov 07 2010 You're right, the real cases where this kind of thing occurs are much mo...
- retard (23/52) Nov 07 2010 That's why we have immutable variables. They force you to think what to
- so (7/29) Nov 07 2010 Not related to this but i have to share.
- Jussi Jumppanen (9/13) Nov 07 2010 void main()
- Nick Sabalausky (10/24) Nov 07 2010 Well I'll be damned, even C/C++ knows that uninitialized variables shoul...
- Walter Bright (8/19) Nov 07 2010 For the code:
- Nick Sabalausky (12/31) Nov 08 2010 Yes, which by your "people will toss something in to shut the compiler u...
- Walter Bright (3/27) Nov 08 2010 I see no reason why people would do that. It doesn't save typing, it isn...
- Walter Bright (3/5) Nov 08 2010 What I mean is that I've never seen anyone do that, and I've seen a lot ...
- so (3/5) Nov 07 2010 I can't see any uninitialized var there, can you? :P
- Nick Sabalausky (9/12) Nov 08 2010 There's no usage of an undeclared variable, but the right-hand-side of t...
- so (7/20) Nov 08 2010 So you want language force you to type either "int x=0;" or "int x=void;...
- Nick Sabalausky (6/24) Nov 08 2010 I tend to get a bit fired up by it because Walter's reasoning on it bein...
- Daniel Gibson (10/31) Nov 09 2010 It gives deterministic results/errors.
- Simen kjaeraas (7/31) Nov 09 2010 Yup. Also, as opposed to certain other solutions, it does not require
- Nick Sabalausky (24/54) Nov 09 2010 First of all, the risks from "shut the compiler up" initalizations are
- Nick Sabalausky (6/37) Nov 09 2010 Also, as I've said when this was discussed in the past, I wouldn't even ...
- Simen kjaeraas (6/11) Nov 09 2010 But if it isn't, we must either define what it should do, or accept that
- bearophile (6/9) Nov 09 2010 Right. There are ways to write formal specs for this too
- Nick Sabalausky (3/12) Nov 09 2010 Agreed.
- Nick Sabalausky (6/39) Nov 09 2010 Where are people getting the idea that I've said C's behavior is better ...
- Nick Sabalausky (5/46) Nov 09 2010 Again, saying "Not giving compile-time errors on reading before writing ...
- so (9/23) Nov 07 2010 I am using VC++ Express 2008, and last time i tried warning level was
- Jussi Jumppanen (12/14) Nov 08 2010 That may well be the case.
- Nick Sabalausky (3/11) Nov 07 2010 Yes, you'd rather silently insert a value even when it's the wrong value...
- Nick Sabalausky (34/83) Nov 07 2010 The problem is values accidentally not being inited. When that happens, ...
- foobar (8/69) Nov 07 2010 Both the current D way and the C# way are ugly hacks.
- spir (8/9) Nov 07 2010 licit about it so it prevents illegal operations at compile time.
- Jonathan M Davis (8/19) Nov 07 2010 Making non-nullable the default would be a seriously breaking change and...
- steveh (2/76) Nov 07 2010 Sounds more retarded than the notorious 'retard' here. It's because of p...
- Denis Koroskin (2/6) Nov 07 2010 Cool down and relax! His post wasn't actually that bad.
- Andrei Alexandrescu (11/17) Nov 07 2010 Clearly it is the preference of some that non-null references are the
- Wyrlon (20/26) Nov 07 2010 Rather than focusing solely at NonNull, I'd prefer to return to the prob...
- Nick Sabalausky (5/9) Nov 07 2010 Ridiculous argument. Even if Walter and Andrei were that petty (they're
- foobar (13/68) Nov 07 2010 You seem to contradict yourself a bit here. As you pointed out yourself ...
- Nick Sabalausky (7/29) Nov 07 2010 It's been awhile since I read that article you linked to, but from what ...
- so (5/12) Nov 07 2010 This is one of the times (and this doesn't happen rarely) i am glad Walt...
- Nick Sabalausky (2/12) Nov 07 2010 How is it total BS?
- so (16/32) Nov 07 2010 If a language is able to avoid bugs caused by uninitialized variables, i...
- Nick Sabalausky (7/33) Nov 07 2010 Yes, and that is *exactly* why I've been saying the compiler should *tra...
- Nick Sabalausky (8/44) Nov 07 2010 I think I figured out what you meant. When I said "C# got it right", you...
- so (5/12) Nov 07 2010 That too, and i am having hard time understanding the other as well, tha...
- Nick Sabalausky (24/34) Nov 08 2010 Example:
- bearophile (10/13) Nov 07 2010 I think all you have written in this post is correct. In this regard D i...
- Nick Sabalausky (8/12) Nov 07 2010 I only read the overview on that page, but it sounds like that could jus...
- bearophile (6/8) Nov 07 2010 Collections, like an array, need a temporary transient state where they ...
1. the INVENTOR of the "reference" concept himself admits that this is a flawed design. see: http://qconlondon.com/london-2009/presentation/Null+References:+The+Billion+Dollar+Mistake 2. "null" is an a type-system attribute, hence should be checked at compile time and would have ZERO affect on run-time performance. Same as assigning a string value to an int variable. 3. the notion of an "undefined" state for a type can be generally implemented by the OPTION type and D pointers are an ad hoc implementation of this concept. see: http://en.wikipedia.org/wiki/Option_type Any type can be wrapped by an OPTION type. trying to do the converse of this is impractical and is bad design. 4. As already pointed by others, Walter's array should be: Option!T[] array; 5. C programmers use null pointers and other special "canary" values as Walter described mainly as rcodes. This is a BAD and bug-prone way of handling errors and is replaced in D by a MUCH better mechanism called "Exceptions". I do NOT want to check for null or zero or NaN throughout my code as if I'm writing c code! This is why D uses signaling NaNs for floats. This accounts for the majority of the uses of null. For the rest just use the option type!
Nov 06 2010
foobar:Any type can be wrapped by an OPTION type. trying to do the converse of this is impractical and is bad design.Discussing this is a waste of time now, this part of the D language will probably never change. This is why other people and me are proposition something different. Bye, bearophile
Nov 06 2010
bearophile Wrote:foobar:I haven't discussed syntax at all so to make clear: I'm not suggesting modifying existing pointers/references. I think D should add Non-Null references (maybe pointers too). I MUCH prefer to use a T! or T or whatever syntax to denote non-null types than to disable constructors. Disabling stuff is a BAD design and is bug-prone. Prime example is Java's clone method which throws an exception by default. The language should be additive, i.e. I should be writing what I want to do, NOT listing all the possible things that I DON'T want to do.Any type can be wrapped by an OPTION type. trying to do the converse of this is impractical and is bad design.Discussing this is a waste of time now, this part of the D language will probably never change. This is why other people and me are proposition something different. Bye, bearophile
Nov 06 2010
Sat, 06 Nov 2010 07:30:56 -0400, foobar wrote:Disabling stuff is a BAD design and is bug-prone. The language should be additive, i.e. I should be writing what I want to do, NOT listing all the possible things that I DON'T want to do.Then why are you here?
Nov 06 2010
retard Wrote:Sat, 06 Nov 2010 07:30:56 -0400, foobar wrote:You just proved your nickname by quoting me out of context.Disabling stuff is a BAD design and is bug-prone. The language should be additive, i.e. I should be writing what I want to do, NOT listing all the possible things that I DON'T want to do.Then why are you here?
Nov 06 2010
On Sat, 06 Nov 2010 13:30:56 +0200, foobar <foo bar.com> wrote:bearophile Wrote:Fine having a nun-null type or ranged integer or special float whatever in a language library, but asking a new syntax for it? Not really. D proved that it is capable of supporting anything in library, if you or Bearophile or anyone else that is after this feature got a library solution, no one would be against it. You all must be out of your minds asking such syntax, Isn't there enough retarded languages have that syntax? Thanks. -- Using Opera's revolutionary email client: http://www.opera.com/mail/foobar:I haven't discussed syntax at all so to make clear: I'm not suggesting modifying existing pointers/references. I think D should add Non-Null references (maybe pointers too). I MUCH prefer to use a T! or T or whatever syntax to denote non-null types than to disable constructors. Disabling stuff is a BAD design and is bug-prone. Prime example is Java's clone method which throws an exception by default. The language should be additive, i.e. I should be writing what I want to do, NOT listing all the possible things that I DON'T want to do.Any type can be wrapped by an OPTION type. trying to do the converseof this is impractical and is bad design. Discussing this is a waste of time now, this part of the D language will probably never change. This is why other people and me are proposition something different. Bye, bearophile
Nov 07 2010
so:Fine having a nun-null type or ranged integer or special float whatever in a language library, but asking a new syntax for it? Not really.There's no way you may implement all the relative semantics in the D language. You and Andrei are wrong. Bye, bearophile
Nov 07 2010
On 11/7/10 10:52 AM, bearophile wrote:so:What's a relative semantics? And what was exactly the claim that was wrong? Thanks, AndreiFine having a nun-null type or ranged integer or special float whatever in a language library, but asking a new syntax for it? Not really.There's no way you may implement all the relative semantics in the D language. You and Andrei are wrong. Bye, bearophile
Nov 07 2010
Andrei Alexandrescu:And what was exactly the claim that was wrong?That there is no need of compiler & syntax support to implement "good enough" nonnullable reference types in D.What's a relative semantics?I've shown; I have explained this five times in recent posts, if you want I may explain again. - Some good solution to the problem of initializing a collection of nonnullable have shown. This too uses a limited form of typestate. But other solutions may be invented that don't require typestates. - Some good solution to the problem of initializing struct/class fields, as explained in the second paper I have linked, regarding "delayed types". Most of that semantics can't be expressed in D, so you need compiler support (and syntax support, but syntax here is very limited, you just need ? notDelayed and something like a "done" for arrays/collections of nonnull references. Syntax is the simplest part of this design). In the end seeing the amount of holes left in the design of the D module system and immutables, this nonnull design may be too much hard for D, most people here don't even see 1/2 of the problems needed to implement nonnullables well enough. So maybe we are just wasting time here. D newsgroup probably needs threads about possible ways to fix/finish the features D2 already has... Bye, bearophile
Nov 07 2010
In the end seeing the amount of holes left in the design of the D module system and immutables, this nonnull design may be too much hard for D, most people here don't even see 1/2 of the problems needed to implement nonnullables well enough. So maybe we are just wasting time here. D newsgroup probably needs threads about possible ways to fix/finish the features D2 already has... Bye, bearophileYou are saying as it is something trivial. :) Const/Immutable is one of the most important and complex part of a language. -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Nov 07 2010
so:You are saying as it is something trivial. :) Const/Immutable is one of the most important and complex part of a language.Sorry, I didn't mean to sound like that. It's indeed hard to design the immutable system of D. And my mind is not good enough yet to design it. Nonetheless there are some important holes left in it. The D module system too is essentially unfinished. To me it is becoming increasingly clear that to design a language you need theories, well rounded lumps of ideas that allow you to implement complex features in a comprehensive way, that don't leave too many large corner cases behind (some corner cases are acceptable in a practical language but too much of them are a sign of a "glued together" language). In the end no language is perfect, but probably many new languages fail not because of misfortune or commercial pressures, but because they are badly designed. Another thing that I have just learnt is that it's quite hard to design a language in community. To design a language you need one, two or three very intelligent persons that interact closely with each other. And probably one of those few persons need to be a "theoretician". Bye, bearophile
Nov 07 2010
On 11/7/10 4:21 PM, bearophile wrote:Andrei Alexandrescu:The only change needed is constructor flow to make sure types with disable'd constructors are always properly initialized. Array construction can be supported with a library function.And what was exactly the claim that was wrong?That there is no need of compiler& syntax support to implement "good enough" nonnullable reference types in D.non-nullables to Java, with which I'm very familiar). I think simpler solutions are available by restricting constructors appropriately.What's a relative semantics?I've shown; I have explained this five times in recent posts, if you want I may explain again. - Some good solution to the problem of initializing a collection of paper I have shown. This too uses a limited form of typestate. But other solutions may be invented that don't require typestates. - Some good solution to the problem of initializing struct/class fields, as explained in the second paper I have linked, regarding "delayed types". Most of that semantics can't be expressed in D, so you need compiler support (and syntax support, but syntax here is very limited, you just need ? notDelayed and something like a "done" for arrays/collections of nonnull references. Syntax is the simplest part of this design).In the end seeing the amount of holes left in the design of the D module system and immutables, this nonnull design may be too much hard for D, most people here don't even see 1/2 of the problems needed to implement nonnullables well enough. So maybe we are just wasting time here. D newsgroup probably needs threads about possible ways to fix/finish the features D2 already has...If there are design holes those need to be known. There is awareness and institutional memory (via bugzilla) about bugs in the implementation. Andrei
Nov 07 2010
Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:On 11/7/10 4:21 PM, bearophile wrote:One more thing: structs with NotNull!T fields will need to have their default constructor disabled automagically. -- SimenAndrei Alexandrescu:The only change needed is constructor flow to make sure types with disable'd constructors are always properly initialized. Array construction can be supported with a library function.And what was exactly the claim that was wrong?That there is no need of compiler& syntax support to implement "good enough" nonnullable reference types in D.
Nov 08 2010
On Monday 08 November 2010 01:10:07 Simen kjaeraas wrote:Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:??? Structs have no default constructor. They have an init property with is used for default initialization. And if you could enforce that a struct be properly initialized rather than default initialized, that would be a big change. Granted, I hate the fact that you can't have default constructors on structs, that you cannot enforce that a struct be initialized instead of default initialized, and that you cannot yet use new in CTFE and therefore have structs whose fields which are references be default initialized to null, but as it stands, you cannot get around the problem. Either init needs to be changed to allow for real default constructors and/or objects need to be legal CTFE - ideally both. But while the second is supposed to happen at some point, there is no sign of it happening any time soon, and there appears to be no sign that the first will ever happen. So, there is not currently a way to have NotNull!T hold anything but null initially when it's a member variable of a struct, and there's no sign of that changing any time soon. It is true, however, that the issue must be resolved for NotNull!T to really work. - Jonathan M DavisOn 11/7/10 4:21 PM, bearophile wrote:One more thing: structs with NotNull!T fields will need to have their default constructor disabled automagically.Andrei Alexandrescu:The only change needed is constructor flow to make sure types with disable'd constructors are always properly initialized. Array construction can be supported with a library function.And what was exactly the claim that was wrong?That there is no need of compiler& syntax support to implement "good enough" nonnullable reference types in D.
Nov 08 2010
Jonathan M Davis <jmdavisProg gmx.com> wrote:??? Structs have no default constructor.True. Disabling the default constructor here means that struct Foo{ disable this(); } Foo f; should halt compilation at Foo f;, and certain other places where a default constructor would normally be used.They have an init property with is used for default initialization.Indeed. And this is different from a default constructor that you can't touch how?And if you could enforce that a struct be properly initialized rather than default initialized, that would be a big change.Indeed. And that is what we are trying to achieve.Either init needs to be changed to allow for real default constructors and/or objects need to be legal CTFE - ideally both.Disabling the default constructor (which ostensibly looks this: this( ) { this = init; }) is a very good step in the right direction. Having proper default constructors would be better, and I can not remember the reason we don't have that.So, there is not currently a way to have NotNull!T hold anything but null initially when it's a member variable of a struct, and there's no sign of that changing any time soon.Indeed, and this will never change - it can't. However, we are arguing that it could be null before the struct's constructor is called, and flow control (or out contracts, if necessary) enforce that it is not null when the constructor returns. I admit I here somewhat miss C++'s initialization lists: struct Foo { NonNull< Bar > bar; Foo( ) : bar( new Bar() ) { } } -- Simen
Nov 08 2010
On Monday, November 08, 2010 05:01:57 Simen kjaeraas wrote:Jonathan M Davis <jmdavisProg gmx.com> wrote:I was not aware of that. I didn't think that you could do that for structs since default constructors are illegal in the first place. It would likely have the negative side effect of making it illegal to put Foo in arrays though, since it wouldn't be possible to fill in the array values with init.??? Structs have no default constructor.True. Disabling the default constructor here means that struct Foo{ disable this(); } Foo f; should halt compilation at Foo f;, and certain other places where a default constructor would normally be used.Default initialization is used all over the place - including both stuff like the declaration Foo f; and in array declarations. Every type is default initialized when not initialized directly, and it has nothing to do with default constructors. init must be known at compile time whereas default constructors are run at runtime. Now, if disabling this() on a struct makes init unuseable, then it does become possible to disallow init, which is potentially very useful, but it could also become a problem with arrays and the like. Regardless, while default constructors and init may be similar for structs, since structs are value types and don't _have_ default constructors, they still aren't the same thing. init is essentially the value _before_ any constructor is called. You just can't have a default one.They have an init property with is used for default initialization.Indeed. And this is different from a default constructor that you can't touch how?It's because we need init, and init must be known at compile time. init gets used a fair bit (such as when you declare an array of a given size and the compiler _must_ initialize all of its elements), and it's vital to how D functions. However, D isn't currently able to insert any code which runs for any init values to default construct them. init must be entirely known at compile time. Depending on exactly how init works, it could be a _huge_ change to try and make a default constructor run instead. init makes a lot of sense as it stands for all types _except_ for structs, but it's definitely problematic for structs. - Jonathan M DavisEither init needs to be changed to allow for real default constructors and/or objects need to be legal CTFE - ideally both.Disabling the default constructor (which ostensibly looks this: this( ) { this = init; }) is a very good step in the right direction. Having proper default constructors would be better, and I can not remember the reason we don't have that.
Nov 08 2010
Jonathan M Davis wrote:On Monday, November 08, 2010 05:01:57 Simen kjaeraas wrote:That's right. The idea is to allow the declaration of a default constructor for structs, but only if it is marked as disabled. Then, any use of the struct that would require default initialization is disallowed. That includes static arrays, and arrays allocated via new. A dynamic array could be constructed using a literal or by appending the values one by one. This implies that a struct containing a field that has a disabled default constructor also cannot be default initialized. Of course, you can defeat these protections by using a cast and encapsulating the code that does that. I believe Andrei was thinking of this when he mentioned using a template to initialize a nonnull array.Jonathan M Davis <jmdavisProg gmx.com> wrote:I was not aware of that. I didn't think that you could do that for structs since default constructors are illegal in the first place. It would likely have the negative side effect of making it illegal to put Foo in arrays though, since it wouldn't be possible to fill in the array values with init.??? Structs have no default constructor.True. Disabling the default constructor here means that struct Foo{ disable this(); } Foo f; should halt compilation at Foo f;, and certain other places where a default constructor would normally be used.
Nov 08 2010
On Monday, November 08, 2010 10:06:35 Walter Bright wrote:Jonathan M Davis wrote:How hard would it really be to insert code wherever a struct's init value is used to default construct it either when the program starts up (for globals) or right after it's declared (for locals)? If you could do that, then I don't see why we couldn't have proper default constructors. All I can assume is that adding that extra code to default construct structs would be painful change to make to dmd, but perhaps there's something else that I'm missing. If that could be done though, it would be a _huge_ improvement. - Jonathan M DavisI was not aware of that. I didn't think that you could do that for structs since default constructors are illegal in the first place. It would likely have the negative side effect of making it illegal to put Foo in arrays though, since it wouldn't be possible to fill in the array values with init.That's right. The idea is to allow the declaration of a default constructor for structs, but only if it is marked as disabled. Then, any use of the struct that would require default initialization is disallowed. That includes static arrays, and arrays allocated via new. A dynamic array could be constructed using a literal or by appending the values one by one. This implies that a struct containing a field that has a disabled default constructor also cannot be default initialized. Of course, you can defeat these protections by using a cast and encapsulating the code that does that. I believe Andrei was thinking of this when he mentioned using a template to initialize a nonnull array.
Nov 08 2010
Jonathan M Davis wrote:How hard would it really be to insert code wherever a struct's init value is used to default construct it either when the program starts up (for globals) or right after it's declared (for locals)? If you could do that, then I don't see why we couldn't have proper default constructors. All I can assume is that adding that extra code to default construct structs would be painful change to make to dmd, but perhaps there's something else that I'm missing. If that could be done though, it would be a _huge_ improvement.There are some severe problems with that approach. One of the largest is the possibility that the default constructor may fail (throw an exception). This has a vast impact on the design of things, and wrecks a lot of generic code that relies on being able to guarantee initialization success.
Nov 08 2010
== Quote from Walter Bright (newshound2 digitalmars.com)'s articleJonathan M Davis wrote:While I'm also skeptical of the idea that simply declaring a variable can cause arbitrarily complex code to be executed, I'll play Devil's Advocate a little: What if we required the default struct constructor to be nothrow? We could also require some level of purity (at least weak pure).How hard would it really be to insert code wherever a struct's init value is used to default construct it either when the program starts up (for globals) or right after it's declared (for locals)? If you could do that, then I don't see why we couldn't have proper default constructors. All I can assume is that adding that extra code to default construct structs would be painful change to make to dmd, but perhaps there's something else that I'm missing. If that could be done though, it would be a _huge_ improvement.There are some severe problems with that approach. One of the largest is the possibility that the default constructor may fail (throw an exception). This has a vast impact on the design of things, and wrecks a lot of generic code that relies on being able to guarantee initialization success.
Nov 08 2010
dsimcha wrote:While I'm also skeptical of the idea that simply declaring a variable can cause arbitrarily complex code to be executed, I'll play Devil's Advocate a little: What if we required the default struct constructor to be nothrow? We could also require some level of purity (at least weak pure).Not a bad idea, but this still leaves people nowhere who need non-trivial construction in order to have a valid object.
Nov 08 2010
On Monday, November 08, 2010 15:23:40 Walter Bright wrote:dsimcha wrote:Well, if it's a default constructer which has to be nothrow and maybe pure or nothing, I'll take the default constructor. Now, if there's a better way to handle this which would result in full-blown, arbitrary default constructors, then that would be better, but something is better than nothing. Another thought relates to the discussion of disable on a struct's default constructor to disable init. What if we allowed default constructors but disabled init in the same way that we'd be doing with disable? So, a struct uses init if it has no default constructor, but if it has one, then you can't use it where init would be required. Would that help fix things? It certainly would make some sense given that when using a default constructor, you don't really want init anyway. It could just be annoying with static arrays and the like (though = void should make it possible to make that work I think, if you really need to). - Jonathan M DavisWhile I'm also skeptical of the idea that simply declaring a variable can cause arbitrarily complex code to be executed, I'll play Devil's Advocate a little: What if we required the default struct constructor to be nothrow? We could also require some level of purity (at least weak pure).Not a bad idea, but this still leaves people nowhere who need non-trivial construction in order to have a valid object.
Nov 08 2010
Jonathan M Davis wrote:Well, if it's a default constructer which has to be nothrow and maybe pure or nothing, I'll take the default constructor. Now, if there's a better way to handle this which would result in full-blown, arbitrary default constructors, then that would be better, but something is better than nothing.I just hate to get into the complex, buggy quagmire C++ has with this.Another thought relates to the discussion of disable on a struct's default constructor to disable init. What if we allowed default constructors but disabled init in the same way that we'd be doing with disable? So, a struct uses init if it has no default constructor, but if it has one, then you can't use it where init would be required. Would that help fix things? It certainly would make some sense given that when using a default constructor, you don't really want init anyway. It could just be annoying with static arrays and the like (though = void should make it possible to make that work I think, if you really need to).Actually, you do as init takes care of most of the initializations, and ensures the fields have predictable values before the ctor starts.
Nov 08 2010
On Monday 08 November 2010 20:10:42 Walter Bright wrote:Jonathan M Davis wrote:We definitely want to avoid the nastier issues, but the lack of default constructors continually pops up as being a major problem. The QtD folks in particular were have a lot of problems because of it as I understand. I've certainly had problems with it my code. Even a restricted default constructor would be better than none.Well, if it's a default constructer which has to be nothrow and maybe pure or nothing, I'll take the default constructor. Now, if there's a better way to handle this which would result in full-blown, arbitrary default constructors, then that would be better, but something is better than nothing.I just hate to get into the complex, buggy quagmire C++ has with this.Okay. Yes init is the state prior to the constructor being run, which is fine - you have the same with classes except that there is no init that you can directly access. The problem is when you can have init _without_ calling a constructor. If we could have default constructors on structs but have it so that any struct with a default constructor cannot be used where you have to have a bare init with no constructor call, then that at least seems like it would mostly solve the problem. In the few places where it's a problem - such as array construction - some kind of library solution could probably solve it (for dynamic arrays at least). - Jonathan M DavisAnother thought relates to the discussion of disable on a struct's default constructor to disable init. What if we allowed default constructors but disabled init in the same way that we'd be doing with disable? So, a struct uses init if it has no default constructor, but if it has one, then you can't use it where init would be required. Would that help fix things? It certainly would make some sense given that when using a default constructor, you don't really want init anyway. It could just be annoying with static arrays and the like (though = void should make it possible to make that work I think, if you really need to).Actually, you do as init takes care of most of the initializations, and ensures the fields have predictable values before the ctor starts.
Nov 08 2010
Jonathan M Davis <jmdavisProg gmx.com> wrote:We definitely want to avoid the nastier issues, but the lack of default constructors continually pops up as being a major problem. The QtD folks in particular were have a lot of problems because of it as I understand. I've certainly had problems with it my code. Even a restricted default constructor would be better than none.In my experience, disabling the default constructor would be enough. That way the compiler warns you that 'this object has no valid default state, so use a constructor.'If we could have default constructors on structs but have it so that any struct with a default constructor cannot be used where you have to have a bare init with no constructor callAnd where is that? Currently no such thing exists, as we have no default constructors for structs. That means we could interpret any use of .init as a constructor call. Disabling default constructors has this same advantage, while avoiding the problems. The only problem is you will have to use a constructor explicitly. -- Simen
Nov 09 2010
On Tuesday 09 November 2010 02:22:31 Simen kjaeraas wrote:Jonathan M Davis <jmdavisProg gmx.com> wrote:Except that I _want_ to have default constructors for structs. Sure, having a struct which can't be used without constructing it (i.e. just using init) and which has no default constructor can be useful, but having default constructors would be _huge_.We definitely want to avoid the nastier issues, but the lack of default constructors continually pops up as being a major problem. The QtD folks in particular were have a lot of problems because of it as I understand. I've certainly had problems with it my code. Even a restricted default constructor would be better than none.In my experience, disabling the default constructor would be enough. That way the compiler warns you that 'this object has no valid default state, so use a constructor.'There has been discussion in the nullable reference thread of making disable this() {} for structs disable init so that you can only use such structs by constructing them, and any place that would use init (such as a static array) would not be legal for such a struct. I'm suggesting that we do something similar to that except that we make it so that having a default constructor disables init and constructing the struct with the default constructor is then one of the legal ones to construct the struct. - Jonathan M DavisIf we could have default constructors on structs but have it so that any struct with a default constructor cannot be used where you have to have a bare init with no constructor callAnd where is that? Currently no such thing exists, as we have no default constructors for structs. That means we could interpret any use of .init as a constructor call. Disabling default constructors has this same advantage, while avoiding the problems. The only problem is you will have to use a constructor explicitly.
Nov 09 2010
Jonathan M Davis <jmdavisProg gmx.com> wrote:I was not aware of that. I didn't think that you could do that for structs since default constructors are illegal in the first place.And you can't. That doesn't mean it can't be possible in the future.It would likely have the negative side effect of making it illegal to put Foo in arrays though, since it wouldn't be possible to fill in the array values with init.Indeed. That's been discussed here, and in short, these are the rules: Arrays of non-null cannot have their lengths increased. To create an array of non-null, use a literal, a function that checks all parameters and builds an array from it, or a function that checks all elements of a passed array of nullable elements. To create a longer array, append two arrays.I mean, the compiler is doing something to move .init to the new instance of the type, and this could very well be considered the default constructor.Default initialization is used all over the place - including both stuff like the declaration Foo f; and in array declarations. Every type is default initialized when not initialized directly, and it has nothing to do with default constructors. init must be known at compile time whereas default constructors are run at runtime.They have an init property with is used for default initialization.Indeed. And this is different from a default constructor that you can't touch how?init gets used a fair bit (such as when you declare an array of a given size and the compiler _must_ initialize all of its elements), and it's vital to how D functions.static arrays would require initializers in this case: NonNull!(T)[2]; // Compile-time error: NonNull!T has no default constructor NonNull!(T)[2] = [nonNull(new T), nonNull(new T)]; // WorksDepending on exactly how init works, it could be a _huge_ change to try and make a default constructor run instead.Possibly, though I don't think so. As said before, some code needs to be executed to copy .init to the new instance. This code could likely be replaced with a default constructor. Even so, the disabling of default constructors is not really about constructors, but as you say, about disabling .init. This will not require execution of new code, only a compile-time check for whether the constructor has been disabled. -- Simen
Nov 08 2010
bearophile Wrote:foobar:I've known there are hidden tradeoffs when using these 'intelligent' types. Non-null types add terrible runtime checks everywhere. It's simply not acceptable in a systems programming language. Operating system kernel uses very efficient uninitialized arrays for buffers. It's crazy to force this non-null hype down our throats. I fail to see why non-null is needed. Sometimes even immutability seems too difficult. You can write safe code, you can write efficient code, and you can Don't think so. No TIOBE? No language shootout entries. We should forget it.Any type can be wrapped by an OPTION type. trying to do the converse of this is impractical and is bad design.Discussing this is a waste of time now, this part of the D language will probably never change. This is why other people and me are proposition something different.
Nov 06 2010
steveh <steveh57 useshotmai.l> wrote:I've known there are hidden tradeoffs when using these 'intelligent' types. Non-null types add terrible runtime checks everywhere. It's simply not acceptable in a systems programming language. Operating system kernel uses very efficient uninitialized arrays for buffers. It's crazy to force this non-null hype down our throats.And here you are sorely mistaken. The point of non-nullable types is the exact opposite. In fact, the only time you need a runtime check is when converting a nullable type to a non-nullable - after that, it's guaranteed not to be null. When in addition there is no way to create a non-nullable variable without initializing it (and possibly checking that the initializing value is not null, if it comes from a nullable source), the result is a great decrease in runtime checks, not an increase. -- Simen
Nov 06 2010
steveh:I've known there are hidden tradeoffs when using these 'intelligent' types.Right, every design has some trade-offs.Non-null types add terrible runtime checks everywhere.This is not true. They may "add" some runtime checks, but in practice you normally need to perform those cheeks anyway, manually. In practice I think nonnull types may even reduce a bit the total number of cheeks present in critical paths (because if you have a nonnull, there is no need to test it again and again, once is enough).It's simply not acceptable in a systems programming language. Operating system kernel uses very efficient uninitialized arrays for buffers. It's crazy to force this non-null hype down our throats.You are just not following the discussion and the things said. The normal pointers and references will keep being used in the same way and they will have no runtime cheeks (the compiler in safe modules may ask in some way for them to be tested before being used, this is a point not discussed enough yet in this thread).I fail to see why non-null is needed.Huge C programs show that many features of D aren't actually necessary, you are able to program and live without them. But I think in theory nonull reference types may help avoid some bug.Sometimes even immutability seems too difficult.It is :-)You can write safe code, you can write efficient code, and you can write simple code. But these can't be the same code!I agree that those are three things difficult to have at the same time. But I think D may allow you to pick two as you like, this is the good thing.It's used in some universities to teach some ideas it contains. It has created has done more than 98% of other languages invented so far.We should forget it.Good ideas should be listened to despite the success of the language that contains them. History of computer languages if *full* of failed languages that have taught ideas to more successful languages. If you ignore the ideas just because they come from a failed language, they you are shutting yourself 95% of the progress and development in the story of language design :-) Bye, bearophile
Nov 06 2010
steveh wrote:Non-null types add terrible runtime checks everywhere. =20No they don't. They *remove* runtime checks everywhere. There are only two possible situations for a given pointer: 1. You know that it cannot be null. In that case, you use a non-nullable type for that pointer to give the information to the compiler. The compiler can then use this information to optimize code better (for example removing null checks inside template instantiations); 2. You don't know if a pointer may be null. In that case, you must check that pointer anyway before using it, so you use a nullable pointer and you're back in the current situation except that the compiler knows to warn you if you forget to check. So what do you gain? Several things: 1. As a library writer, if your function cannot work with a null input, instead of checking the function argument and erroring if it is null, you just use a non-nullable type which pushes the check in the user code where it can be removed altogether in lots of cases; 2. Generic code (templates and mixins) may be optimized better: when generic code includes a null check, the compiler can remove it if it is applied to a non-nullable type; 3. And overall, you get safer code because if you forget to check a nullable pointer, then the compiler can tell you. Note that adding non-nullable types has *nothing* to do with automatically adding hidden runtime checks. I personally think that adding such checks automatically is a bad idea in a "system" language. The proper behaviour should be for the compiler to give an error message (*) so that the programmer can take a look and choose between using a check or changing to a non-nullable pointer. Jerome (*) I didn't say a warning, because I know Walter's view on them, but it could be a warning instead of an error. --=20 mailto:jeberger free.fr http://jeberger.free.fr Jabber: jeberger jabber.fr
Nov 06 2010
On 11/6/2010 6:50 AM, bearophile wrote:foobar:I still live in D1 land, so forgive me if I'm out of the loop--but what keeps this from being implemented at the library level as templated type: NotNull!(T) ? If there are limitations, maybe these areas of the language can be improved to get us there?Any type can be wrapped by an OPTION type. trying to do the converse of this is impractical and is bad design.Discussing this is a waste of time now, this part of the D language will probably never change. This is why other people and me are proposition something different. Bye, bearophile
Nov 07 2010
Eric Poggel <dnewsgroup2 yage3d.net> wrote:On 11/6/2010 6:50 AM, bearophile wrote:blocker. There are other problems, mostly related to this - classes and structs with NotNull!T fields must define a constructor, and for structs that means the default destructor either needs to be possible to define or possible to disable. Arrays of NotNull!T may not be resized to a greater length, as that would require calling the default constructor of NotNull!T. I think that's it. -- Simenfoobar:I still live in D1 land, so forgive me if I'm out of the loop--but what keeps this from being implemented at the library level as templated type: NotNull!(T) ? If there are limitations, maybe these areas of the language can be improved to get us there?Any type can be wrapped by an OPTION type. trying to do the converse of this is impractical and is bad design.Discussing this is a waste of time now, this part of the D language will probably never change. This is why other people and me are proposition something different. Bye, bearophile
Nov 08 2010
On Mon, 08 Nov 2010 12:08:01 +0300, Simen kjaeraas <simen.kjaras gmail.com> wrote:Eric Poggel <dnewsgroup2 yage3d.net> wrote:Not exactly disabled. The following should work: class Foo { this() { bar = new Object(); } NonNull!(Object) bar; // fine here } while the following shouldn't: NonNull!(Object) bar; // error here bar = new Object();On 11/6/2010 6:50 AM, bearophile wrote:blocker. There are other problems, mostly related to this - classes and structs with NotNull!T fields must define a constructor, and for structs that means the default destructor either needs to be possible to define or possible to disable. Arrays of NotNull!T may not be resized to a greater length, as that would require calling the default constructor of NotNull!T. I think that's it.foobar:I still live in D1 land, so forgive me if I'm out of the loop--but what keeps this from being implemented at the library level as templated type: NotNull!(T) ? If there are limitations, maybe these areas of the language can be improved to get us there?Any type can be wrapped by an OPTION type. trying to do the converse of this is impractical and is bad design.Discussing this is a waste of time now, this part of the D language will probably never change. This is why other people and me are proposition something different. Bye, bearophile
Nov 08 2010
Denis Koroskin <2korden gmail.com> wrote:On Mon, 08 Nov 2010 12:08:01 +0300, Simen kjaeraas <simen.kjaras gmail.com> wrote:I belive you have misunderstood me. The NonNull struct would need to have its default constructor disabled. Then, extra logic would need to be added to class and struct constructors to ensure NonNull fields have their constructors called. Context-sensitive constructor disabling is a theoretical possibility, but seems to me to conflict with D's other goals. -- SimenEric Poggel <dnewsgroup2 yage3d.net> wrote:Not exactly disabled. The following should work: class Foo { this() { bar = new Object(); } NonNull!(Object) bar; // fine here } while the following shouldn't: NonNull!(Object) bar; // error here bar = new Object();On 11/6/2010 6:50 AM, bearophile wrote:blocker. There are other problems, mostly related to this - classes and structs with NotNull!T fields must define a constructor, and for structs that means the default destructor either needs to be possible to define or possible to disable. Arrays of NotNull!T may not be resized to a greater length, as that would require calling the default constructor of NotNull!T. I think that's it.foobar:I still live in D1 land, so forgive me if I'm out of the loop--but what keeps this from being implemented at the library level as templated type: NotNull!(T) ? If there are limitations, maybe these areas of the language can be improved to get us there?Any type can be wrapped by an OPTION type. trying to do the converse of this is impractical and is bad design.Discussing this is a waste of time now, this part of the D language will probably never change. This is why other people and me are proposition something different. Bye, bearophile
Nov 08 2010
Simen kjaeraas:Context-sensitive constructor disabling is a theoretical possibility, but seems to me to conflict with D's other goals.It's time to update those goals. Bye, bearophile
Nov 08 2010
bearophile Wrote:Simen kjaeraas:I studied the situation further. Now I've decided to leave D. I tried to cope with all overly complex type system quirks, but have had enough of it now. These two months with D truly opened my eyes. It means I won't touch C++ or Java either. My next goal is to use an untyped (less types = better) language which concentrates on cool syntax. Intensive test suites guarantee safety and quality. An extreme version of TDD. I'm building an IDE (Eclipse) extension [in Java :( ] for automatically injecting basic tests to typical programs. This way the tests only slow down the debug build. The production version runs at maximum speed. Another solution is exploratory testing. I test stuff interactively using a REPL. These reports and guidelines can be written down in .doc word documents. I learnt this idea from Paul Graham and his new language.Context-sensitive constructor disabling is a theoretical possibility, but seems to me to conflict with D's other goals.It's time to update those goals.
Nov 08 2010
steveh Wrote:bearophile Wrote:Your conclusion that less types = better is patently incorrect. While I like Ruby and test driven development that doesn't obviate the need for a strong type system. tests can only prove that whatever invalid inputs you test for are accounted for. Tests CANNOT prove the correctness of your system for all inputs. Frankly, I wouldn't use software you wrote with this attitude for a facebook app let alone any system with a smidgen of reliability requirements.Simen kjaeraas:I studied the situation further. Now I've decided to leave D. I tried to cope with all overly complex type system quirks, but have had enough of it now. These two months with D truly opened my eyes. It means I won't touch C++ or Java either. My next goal is to use an untyped (less types = better) language which concentrates on cool syntax. Intensive test suites guarantee safety and quality. An extreme version of TDD. I'm building an IDE (Eclipse) extension [in Java :( ] for automatically injecting basic tests to typical programs. This way the tests only slow down the debug build. The production version runs at maximum speed. Another solution is exploratory testing. I test stuff interactively using a REPL. These reports and guidelines can be written down in .doc word documents. I learnt this idea from Paul Graham and his new language.Context-sensitive constructor disabling is a theoretical possibility, but seems to me to conflict with D's other goals.It's time to update those goals.
Nov 08 2010
foobar:While I like Ruby and test driven development that doesn't obviate the need for a strong type system. tests can only prove that whatever invalid inputs you test for are accounted for. Tests CANNOT prove the correctness of your system for all inputs.In practice on average my small Python programs are less buggy than my small D ones. Anyway, in D I use the static type system, many unittests, design by contract, all together at the same time, and sometimes they aren't enough, I'd like a bit of static analysis too (as done by lints or better by more sophisticated languages), or automatic fuzzy tests :-) Bye, bearophile
Nov 08 2010
bearophile wrote:In practice on average my small Python programs are less buggy than my small D ones.One's experience with a particular language can have a very strong influence on how buggy one's code is. D's type system is also designed for large systems. For small programs, static typing is largely irrelevant.
Nov 08 2010
Intensive test suites guarantee safety and quality. An extreme version of TDD.sounds good, but strong typesystem pissed poeple normaly don't tend to write such suit code - they just talk about writing it and btw: TDD means Test Driven Development, but in real life it seems to be Trial Driven Development
Nov 08 2010
steveh wrote:less types = betterThen no types are best? Do have some fun with assembler. -manfred
Nov 08 2010
I studied the situation further. Now I've decided to leave D. I tried to cope with all overly complex type system quirks, but have had enough of it now. These two months with D truly opened my eyes. It means I won't touch C++ or Java either. My next goal is to use an untyped (less types = better) language which concentrates on cool syntax. Intensive test suites guarantee safety and quality. An extreme version of TDD. I'm building an IDE (Eclipse) extension [in Java :( ] for automatically injecting basic tests to typical programs. This way the tests only slow down the debug build. The production version runs at maximum speed. Another solution is exploratory testing. I test stuff interactively using a REPL. These reports and guidelines can be written down in .doc word documents. I learnt this idea from Paul Graham and his new language.Your choice is perfectly reasonable, you use static typed languages because there is no other way, and you need it. If you think a simpler language can do it for you, you don't need D like languages to begin with :) -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Nov 08 2010
On 08/11/2010 14:35, steveh wrote:bearophile Wrote:I'm often hearing that argument from the new dynamic languages crowd: that less types = better, and that lots of tests guarantee safety and quality. * lifts hands * What they don't realize, is that static typing is just compile-time unit-testing. :) * hands the spoon back to Neo *Simen kjaeraas:I studied the situation further. Now I've decided to leave D. I tried to cope with all overly complex type system quirks, but have had enough of it now. These two months with D truly opened my eyes. It means I won't touch C++ or Java either. My next goal is to use an untyped (less types = better) language which concentrates on cool syntax. Intensive test suites guarantee safety and quality. An extreme version of TDD.Context-sensitive constructor disabling is a theoretical possibility, but seems to me to conflict with D's other goals.It's time to update those goals.Another solution is exploratory testing. I test stuff interactively using a REPL. These reports and guidelines can be written down in .doc word documents. I learnt this idea from Paul Graham and his new language.Paul Graham. lol. -- Bruno Medeiros - Software Engineer
Nov 25 2010
On Thu, 25 Nov 2010 16:14:11 +0000 Bruno Medeiros <brunodomedeiros+spam com.gmail> wrote:What they don't realize, is that static typing is just compile-time=20 unit-testing. :)I tried to find some light on this topic a while ago, because similar argum= ents are constantly brought on the carpet, but I have never read any ration= ale, even less a report from an experimental study. Would be interesting; b= ut what is to measure, exactly? For a while, I have used nearly only dynamic languages; and I had bugs, som= e of them really naughty. Then about 2 years I passed on the stacic far mor= e bugs, most of them not naughty at all. The sheer wasx partly due to less = experience, but also because there are many more oportunities for bugs to c= ome up, from plain language complexity (not only of syntax). I start to appreciate static checking. During the first "static" year, I us= ed mainly freepascal and can say I had about _no_ type error -- what static= checking is here to catch, I guess. I think the reason was that during tho= se dynamic years I had developed a kind of unconscious type rigor both on t= he modeling & the implementation sides of the coin. These, I get many of them ;-) Wildly counted, after 1 hour typing without c= ompilation, I get a dozen compiler errors, 1 serious, 2-3 type errors, the = rest plain grammatical. I guess i'm slowly losing this purely mental typing= discipline: static checking makes my brain lazy ;-); it relies on the comp= iler instead of thinking clearly. Or it's just age... More seriously, I tried to classify programming errors. Let's say one need = to model dice. After all irrelevant aspect removed, just remains equiprobab= le alea in a natural interval. 1. Modeling error: bite hard -- using a distribution that does not provide = equiprobability. 2. Translation error: hurt as well -- random.int(1,6) actually returns in i= nterval [1,5]. 3. Implementation error: eg uint<-->int issues. Depending on the language, = this risk may be caught or not. (Yes, there should be a huge number of dice= with a huge number of faces...) 4. Grammatical error: except for beginners, harmless. Phase 2-->3 is, for me, where we pass from human (model) semantic to langua= ge semantics. I guess that's where type issues may come up. I'm aware this classification is personal, arbitrary, not based on any fact= . Just tried to think about the question: what kinds of bugs do Type Errors= reveal? Denis -- -- -- -- -- -- -- vit esse estrany =E2=98=A3 spir.wikidot.com
Nov 25 2010
"foobar" <foo bar.com> wrote in message news:ib3a8k$1i58$1 digitalmars.com...1. the INVENTOR of the "reference" concept himself admits that this is a flawed design. see: http://qconlondon.com/london-2009/presentation/Null+References:+The+Billion+Dollar+MistakeFirst of all, "appeal to authority" is a logical fallacy. Second, there are plenty of cases where run-time nullability is useful and where lack of it is problematic at best: A tree or linked list, for example. The "null object" idiom doesn't count, because all it does is just reinvent null, and in a pointlessly roundabout way.2. "null" is an a type-system attribute, hence should be checked at compile time and would have ZERO affect on run-time performance. Same as assigning a string value to an int variable.I strongly agree with this. On a related note, I *hate* that D silently sticks in a default value whenever anything isn't properly inited. This is one thing where I really it with an undefined value like C does!" banner is an irritating strawman: Yea, it's better than C, but it still sucks. I also dislike that D's reference types being nullable by default is inconsistent with its value types. (Yea, naturally reference and value types are going to have inherent differences, but nullability shouldn't be one of them.)3. the notion of an "undefined" state for a type can be generally implemented by the OPTION type and D pointers are an ad hoc implementation of this concept. see: http://en.wikipedia.org/wiki/Option_type Any type can be wrapped by an OPTION type. trying to do the converse of this is impractical and is bad design.I strongly agree with this, too.4. As already pointed by others, Walter's array should be: Option!T[] array;Only if you actually *want* to allow null elements.5. C programmers use null pointers and other special "canary" values as Walter described mainly as rcodes. This is a BAD and bug-prone way of handling errors and is replaced in D by a MUCH better mechanism called "Exceptions".Absolutely agree.
Nov 06 2010
On Saturday 06 November 2010 19:05:32 Nick Sabalausky wrote:"foobar" <foo bar.com> wrote in messagend in a pointlessly roundabout way.initialize variables even in cases where they know that it's not necessary (which is annoying but may or may not be worth it), but more importantly (from Walter's perspective at least), it would require flow analysis, which he actively avoids. Using default values avoids memory bugs like you get in C and results in a simpler compiler implementation (and therefore a less bug-prone one) and makes it simpler for other tools to be written for the language. Now, it may be that declaring variables without initializing them (which generally should be avoided regardless), it generally doesn't matter. Also, it's essentially D's stance that not initializing a variable is a bug, so every variable is default initialized to the closest to an error value that exists for that type. null is the obvious choice for pointers and references. I'm moderately divided on the issue, but ultimately, I think that D's decision what D does works quite well.2. "null" is an a type-system attribute, hence should be checked at compile time and would have ZERO affect on run-time performance. Same as assigning a string value to an int variable.I strongly agree with this. On a related note, I *hate* that D silently sticks in a default value whenever anything isn't properly inited. This is one thing where I really it with an undefined value like C does!" banner is an irritating strawman: Yea, it's better than C, but it still sucks.I also dislike that D's reference types being nullable by default is inconsistent with its value types. (Yea, naturally reference and value types are going to have inherent differences, but nullability shouldn't be one of them.)It's not at all inconsistent if you look at from the perspective that types are default initialized to the closest thing to an error value that they have. Many of the value types (such as the integral types), don't really have a value that's an obvious error, so they don't fit in with that quite so well, but it's unavoidable given that they just don't have an obvious error value. And I don't understand why you think that nullability shouldn't be a difference between value types and reference types. That's one of the _key_ differences between them. Value types _cannot_ be null, while references can. And I'd sure hate to _not_ be able to have a null reference. It's irritating enough that arrays and associative arrays are almost treated the same when they're null as when they're empty. I can totally understand wanting non-nullable reference types. There are plenty of times where it just doesn't make sense to a have a variable which can be null - even if it's a reference - but there are plenty of cases where it _does_ make sense, and I do find the fact that D default initializes to error values to be quite useful, since I do consider it bad practice in general to not initialize a variable when it's declared. Sometimes you have to for scoping reasons or whatnot, but generally, variables _should_ be initialized when declared. - Jonathan M Davis
Nov 06 2010
Jonathan M Davis wrote:initialize variables even in cases where they know that it's not necessary (which is annoying but may or may not be worth it),Correct. It's not that doing flow analysis is hard, it's that it's impossible to do it correctly. So you wind up with wishy-washy messages that p "might not" be initialized, which is what the Java compiler does for this: class A { public void foo() { Object p; if (m) p = new Object(); if (m) p.toString(); // <-- p might not have been initialized } boolean m; } It even errors out if you write it as: class A { public void foo() { Object p; if (m) p = new Object(); if (p != null) // <-- p might not have been initialized p.toString(); } boolean m; } Note that the error message is on the null check!
Nov 06 2010
"Walter Bright" <newshound2 digitalmars.com> wrote in message news:ib5bue$2ldp$1 digitalmars.com...Jonathan M Davis wrote:Since when should crap like that ever be written in the first place? In a code review, I'd slap both of those with a giant red "convoluted" stamp, *especially* if it's not just a trivial example like those. Besides, I'd much rather have easily-fixable false positives like that then the false negatives D gets now: Object p; if (m) p = new Object(); p.toString(); // Boom!, but *only* at run-time, and *only* if m just happens to be true. Plus, as I've argued before, I *wouldn't* want perfect flow analysis on that, I'd rather have easily-rememberable rules. If the initialization-safety of your code is dependent on complex logic, then you've written it wrong anyway. In simple examples like yours above, the fixes are not only obvious, but much more clear: Object p; if (m) { p = new Object(); p.toString(); } And in more complex cases, relying on complex logic to ensure things are inited properly is just wrong anyway, as I said above. Seriously, this whole "feature" amounts to nothing more than allowing the following *broken* code to occasionally get overlooked... Object p; if (m) p = new Object(); p.toString(); ...just for the completely non-existent "convenience" of writing crap like this... Object p; if (m) p = new Object(); if (m) p.toString(); ...instead of just doing it right: Object p; if (m) { p = new Object(); p.toString(); } still a hell of a lot better than "wrong", which is what D does (as evidenced by my first example above).even in cases where they know that it's not necessary (which is annoying but may or may not be worth it),Correct. It's not that doing flow analysis is hard, it's that it's impossible to do it correctly. So you wind up with wishy-washy messages that p "might not" be initialized, which is what the Java compiler does for this: class A { public void foo() { Object p; if (m) p = new Object(); if (m) p.toString(); // <-- p might not have been initialized } boolean m; } It even errors out if you write it as: class A { public void foo() { Object p; if (m) p = new Object(); if (p != null) // <-- p might not have been initialized p.toString(); } boolean m; } Note that the error message is on the null check!
Nov 06 2010
"Nick Sabalausky" <a a.a> wrote in message news:ib5ht0$2uff$1 digitalmars.com..."Walter Bright" <newshound2 digitalmars.com> wrote in message news:ib5bue$2ldp$1 digitalmars.com...Additionally, the root problem with default values is that they make deliberately-default-inited declarations and accidentally-uninited declarations completely indistinguishable by both the compiler and the programmer. (And no, "accidentally-uninited" does *not* imply "undefined value". If something's supposed be inited to X and it gets inited to Y, that's still *wrong* - *even* if it's reproducibly-wrong.)Jonathan M Davis wrote:Since when should crap like that ever be written in the first place? In a code review, I'd slap both of those with a giant red "convoluted" stamp, *especially* if it's not just a trivial example like those. Besides, I'd much rather have easily-fixable false positives like that then the false negatives D gets now: Object p; if (m) p = new Object(); p.toString(); // Boom!, but *only* at run-time, and *only* if m just happens to be true. Plus, as I've argued before, I *wouldn't* want perfect flow analysis on that, I'd rather have easily-rememberable rules. If the initialization-safety of your code is dependent on complex logic, then you've written it wrong anyway. In simple examples like yours above, the fixes are not only obvious, but much more clear: Object p; if (m) { p = new Object(); p.toString(); } And in more complex cases, relying on complex logic to ensure things are inited properly is just wrong anyway, as I said above. Seriously, this whole "feature" amounts to nothing more than allowing the following *broken* code to occasionally get overlooked... Object p; if (m) p = new Object(); p.toString(); ...just for the completely non-existent "convenience" of writing crap like this... Object p; if (m) p = new Object(); if (m) p.toString(); ...instead of just doing it right: Object p; if (m) { p = new Object(); p.toString(); } that's still a hell of a lot better than "wrong", which is what D does (as evidenced by my first example above).even in cases where they know that it's not necessary (which is annoying but may or may not be worth it),Correct. It's not that doing flow analysis is hard, it's that it's impossible to do it correctly. So you wind up with wishy-washy messages that p "might not" be initialized, which is what the Java compiler does for this: class A { public void foo() { Object p; if (m) p = new Object(); if (m) p.toString(); // <-- p might not have been initialized } boolean m; } It even errors out if you write it as: class A { public void foo() { Object p; if (m) p = new Object(); if (p != null) // <-- p might not have been initialized p.toString(); } boolean m; } Note that the error message is on the null check!
Nov 06 2010
Sun, 07 Nov 2010 01:54:24 -0500, Nick Sabalausky wrote:"Nick Sabalausky" <a a.a> wrote in message news:ib5ht0$2uff$1 digitalmars.com...When I started with D, some of the main reasons for choosing D were: - you can return int from a void function without compilation errors - you can use 'void main()' instead of 'int main()' and a silly return value 0 - counter variables are default initialized to 0 I thought it would save so much typing."Walter Bright" <newshound2 digitalmars.com> wrote in message news:ib5bue$2ldp$1 digitalmars.com...Additionally, the root problem with default values is that they make deliberately-default-inited declarations and accidentally-uninited declarations completely indistinguishable by both the compiler and the programmer. (And no, "accidentally-uninited" does *not* imply "undefined value". If something's supposed be inited to X and it gets inited to Y, that's still *wrong* - *even* if it's reproducibly-wrong.)Jonathan M Davis wrote:Since when should crap like that ever be written in the first place? In a code review, I'd slap both of those with a giant red "convoluted" stamp, *especially* if it's not just a trivial example like those. Besides, I'd much rather have easily-fixable false positives like that then the false negatives D gets now: Object p; if (m) p = new Object(); p.toString(); // Boom!, but *only* at run-time, and *only* if m just happens to be true. Plus, as I've argued before, I *wouldn't* want perfect flow analysis on that, I'd rather have easily-rememberable rules. If the initialization-safety of your code is dependent on complex logic, then you've written it wrong anyway. In simple examples like yours above, the fixes are not only obvious, but much more clear: Object p; if (m) { p = new Object(); p.toString(); } And in more complex cases, relying on complex logic to ensure things are inited properly is just wrong anyway, as I said above. Seriously, this whole "feature" amounts to nothing more than allowing the following *broken* code to occasionally get overlooked... Object p; if (m) p = new Object(); p.toString(); ...just for the completely non-existent "convenience" of writing crap like this... Object p; if (m) p = new Object(); if (m) p.toString(); ...instead of just doing it right: Object p; if (m) { p = new Object(); p.toString(); } that's still a hell of a lot better than "wrong", which is what D does (as evidenced by my first example above).variables even in cases where they know that it's not necessary (which is annoying but may or may not be worth it),Correct. It's not that doing flow analysis is hard, it's that it's impossible to do it correctly. So you wind up with wishy-washy messages that p "might not" be initialized, which is what the Java compiler does for this: class A { public void foo() { Object p; if (m) p = new Object(); if (m) p.toString(); // <-- p might not have been initialized } boolean m; } It even errors out if you write it as: class A { public void foo() { Object p; if (m) p = new Object(); if (p != null) // <-- p might not have been initialized p.toString(); } boolean m; } Note that the error message is on the null check!
Nov 07 2010
On 11/7/2010 1:02 AM, Walter Bright wrote:Jonathan M Davis wrote:I know what your mean, but the example is flawed: public void foo() { if (m) { Object p = new Object(); p.toString(); } } ... Thing is, I don't think you really _need_ flow analysis to implement nonnulity. The simplest way is to disallow creation of unitialized nonnull variables. I think it would work, but without some clever syntax such rule would be painful to follow for the programmers. Things like these would be prohibited, for example Duck d; if (b) d = new Duck(); else d = new DuckSubclass(); Seems like a big loss, but it really isn't. Duck d = b ? new Duck() : new DuckSubclass(); But ternary ops are not generic, unless you chain them which is super-ugly. Is there nothing that can fix this? Delegates probably can: enum Dri { one, two, three}; Dri s = Dri.two; int x = { if (s == Dri.one) return 1; else if (s == Dri.two) return 2; else return 3; }(); This works. I'm not sure how efficient it is, but that would solve the issue with initialization without any path analysis. If there was a clearer, more efficient syntax for this, it would work even better. int x = do { if (s == Dri.one) return 1; else if (s == Dri.two) return 2; else return 3; };even in cases where they know that it's not necessary (which is annoying but may or may not be worth it),Correct. It's not that doing flow analysis is hard, it's that it's impossible to do it correctly. So you wind up with wishy-washy messages that p "might not" be initialized, which is what the Java compiler does for this: class A { public void foo() { Object p; if (m) p = new Object(); if (m) p.toString(); // <-- p might not have been initialized } boolean m; } It even errors out if you write it as: class A { public void foo() { Object p; if (m) p = new Object(); if (p != null) // <-- p might not have been initialized p.toString(); } boolean m; } Note that the error message is on the null check!
Nov 07 2010
On 11/7/2010 10:51 AM, Roman Ivanov wrote:On 11/7/2010 1:02 AM, Walter Bright wrote:OF course, the code above assumes that Duck is unnulable. I didn't want to make my own syntax for it, because it would obfuscate the example.Jonathan M Davis wrote:I know what your mean, but the example is flawed: public void foo() { if (m) { Object p = new Object(); p.toString(); } } ... Thing is, I don't think you really _need_ flow analysis to implement nonnulity. The simplest way is to disallow creation of unitialized nonnull variables. I think it would work, but without some clever syntax such rule would be painful to follow for the programmers. Things like these would be prohibited, for example Duck d; if (b) d = new Duck(); else d = new DuckSubclass(); Seems like a big loss, but it really isn't. Duck d = b ? new Duck() : new DuckSubclass(); But ternary ops are not generic, unless you chain them which is super-ugly. Is there nothing that can fix this? Delegates probably can: enum Dri { one, two, three}; Dri s = Dri.two; int x = { if (s == Dri.one) return 1; else if (s == Dri.two) return 2; else return 3; }(); This works. I'm not sure how efficient it is, but that would solve the issue with initialization without any path analysis. If there was a clearer, more efficient syntax for this, it would work even better. int x = do { if (s == Dri.one) return 1; else if (s == Dri.two) return 2; else return 3; };even in cases where they know that it's not necessary (which is annoying but may or may not be worth it),Correct. It's not that doing flow analysis is hard, it's that it's impossible to do it correctly. So you wind up with wishy-washy messages that p "might not" be initialized, which is what the Java compiler does for this: class A { public void foo() { Object p; if (m) p = new Object(); if (m) p.toString(); // <-- p might not have been initialized } boolean m; } It even errors out if you write it as: class A { public void foo() { Object p; if (m) p = new Object(); if (p != null) // <-- p might not have been initialized p.toString(); } boolean m; } Note that the error message is on the null check!
Nov 07 2010
Roman Ivanov <isroman.DEL ete.km.ru> wrote:I know what your mean, but the example is flawed: public void foo() { if (m) { Object p = new Object(); p.toString(); } }You misunderstand. The idea is this: void foo( ) { Object p; if ( m ) { p = new Object( ); p.DoSomethingThatNeedsToBeDoneNow( ); } // 20 lines of code here if ( m ) { p.doSomethingWeird( dataFromAbove ); } }int x = { if (s == Dri.one) return 1; else if (s == Dri.two) return 2; else return 3; }(); This works. I'm not sure how efficient it is, but that would solve the issue with initialization without any path analysis.I'm not sure the compiler actually does this, but it would be fairly trivial to inline that delegate. -- Simen
Nov 07 2010
"Simen kjaeraas" <simen.kjaras gmail.com> wrote in message news:op.vls9bigxvxi10f biotronic-pc.lan...Roman Ivanov <isroman.DEL ete.km.ru> wrote:If you do that, then there's two possibilities: A. You intended p to get inited on all code paths but forgot a codepath. With real init-checking the compiler will tell you and you can fix it. With D as it is, you're not informed at all, and you may or may not catch the problem before deployment. Obviously the former is better. B. You *intended* p to not always be inited, in which case the correct code is this: void foo( ) { Object p=null; if ( m ) { p = new Object( ); p.DoSomethingThatNeedsToBeDoneNow( ); } // 20 lines of code here if ( p != null ) { p.doSomethingWeird( dataFromAbove ); } } And with by-default non-nullability and a good optional "Nullable" system, it would be something like this (Completely made-up syntax for "Nullable!Object", don't nitpick it), which would be far safer: void foo( ) { Nullable!Object p=null; if ( m ) { p = new Object( ); // Compiler knows p is really "Object" instead of "Nullable!Object" // from here to the end of scope, or until p is potentially reassigned. p.DoSomethingThatNeedsToBeDoneNow( ); } // 20 lines of code here p.toString(); // Compile-time error, p might be null // 20 lines of code here if ( p != null ) { // Compiler knows p is really "Object" instead of "Nullable!Object" inside here p.doSomethingWeird( dataFromAbove ); } }I know what your mean, but the example is flawed: public void foo() { if (m) { Object p = new Object(); p.toString(); } }You misunderstand. The idea is this: void foo( ) { Object p; if ( m ) { p = new Object( ); p.DoSomethingThatNeedsToBeDoneNow( ); } // 20 lines of code here if ( m ) { p.doSomethingWeird( dataFromAbove ); } }
Nov 07 2010
Nick Sabalausky <a a.a> wrote:If you do that, then there's two possibilities: A. You intended p to get inited on all code paths but forgot a codepath. With real init-checking the compiler will tell you and you can fix it. With D as it is, you're not informed at all, and you may or may not catch the problem before deployment. Obviously the former is better. B. You *intended* p to not always be inited, in which case the correct code is this: void foo( ) { Object p=null; if ( m ) { p = new Object( ); p.DoSomethingThatNeedsToBeDoneNow( ); } // 20 lines of code here if ( p != null ) { p.doSomethingWeird( dataFromAbove ); } }There is a third option, wherein the if condition will only be true if p !is null, but the actual condition is more complex: if ( m > 4 ) { p = new Object( ); p.DoSomethingThatNeedsToBeDoneNow( ); } // code if ( m > 12 ) { p.doSomethingWeird( dataFromAbove ); } -- Simen
Nov 07 2010
"Simen kjaeraas" <simen.kjaras gmail.com> wrote in message news:op.vltiombuvxi10f biotronic-pc.lan...Nick Sabalausky <a a.a> wrote:- if ( m > 12 ) { + if ( p && m > 12 ) { And you can toss in an "if(m>12) assert(p);" if you're worried about that.If you do that, then there's two possibilities: A. You intended p to get inited on all code paths but forgot a codepath. With real init-checking the compiler will tell you and you can fix it. With D as it is, you're not informed at all, and you may or may not catch the problem before deployment. Obviously the former is better. B. You *intended* p to not always be inited, in which case the correct code is this: void foo( ) { Object p=null; if ( m ) { p = new Object( ); p.DoSomethingThatNeedsToBeDoneNow( ); } // 20 lines of code here if ( p != null ) { p.doSomethingWeird( dataFromAbove ); } }There is a third option, wherein the if condition will only be true if p !is null, but the actual condition is more complex: if ( m > 4 ) { p = new Object( ); p.DoSomethingThatNeedsToBeDoneNow( ); } // code if ( m > 12 ) { p.doSomethingWeird( dataFromAbove ); }
Nov 07 2010
Nick Sabalausky <a a.a> wrote:- if ( m > 12 ) { + if ( p && m > 12 ) { And you can toss in an "if(m>12) assert(p);" if you're worried about that.Of course. But the point is, this is unnecessary. We know p !is null when m > 4. -- Simen
Nov 07 2010
"Simen kjaeraas" <simen.kjaras gmail.com> wrote in message news:op.vltjpebhvxi10f biotronic-pc.lan...Nick Sabalausky <a a.a> wrote:And my point is, the need to write it the way you described is unnecessary and frankly, error prone. So if better safety can be obtained by ditching a useless style that really shouldn't be used anyway, I say we should go for it.- if ( m > 12 ) { + if ( p && m > 12 ) { And you can toss in an "if(m>12) assert(p);" if you're worried about that.Of course. But the point is, this is unnecessary. We know p !is null when m > 4.
Nov 07 2010
Simen kjaeraas wrote:You misunderstand. The idea is this: void foo( ) { Object p; if ( m ) { p = new Object( ); p.DoSomethingThatNeedsToBeDoneNow( ); } // 20 lines of code here if ( m ) { p.doSomethingWeird( dataFromAbove ); } }You're right, the real cases where this kind of thing occurs are much more complex. I just posted the thing boiled down. And, of course, there's always a way to refactor the code to eliminate the spurious error message. But sometimes the result is as ugly as Pascal's efforts to prove you really don't need a 'break' statement in a loop. The real problem with the spurious errors is that then people will put in an initialization "just to shut the compiler up." Time passes, and the next guy is looking at the code and wonders why x is being initialized to a value that is apparently never used, or worse, is initialized to some bogus value randomly picked by the long-retired programmer. I've seen code reviewers losing a lot of time on this issue. In general, I am opposed to inserting dead code and unused values to get the compiler to accept the program. It makes the code harder to reason about. Everything in the code should have a purpose that goes towards understanding the code. If there's: int x = 0; then it stands to reason that: 1. 0 is a valid value for whatever x is subsequently used for 2. this value of x is actually used When both of these are false, it is obfuscation and counterproductive.
Nov 07 2010
Sun, 07 Nov 2010 14:09:01 -0800, Walter Bright wrote:Simen kjaeraas wrote:That's why we have immutable variables. They force you to think what to put in the variables. A lot of cases like the one above would be solved if if-then-else was an functional expression instead of a void returning statement. C/C++/D has the ternary ?: but the syntax is obfuscated. Object p = if (m) { ... foo; } else { ... bar; } instead of Object p; if (m) { ... p = foo; } else { ... p = bar; } There are even cases where the former can be const. The latter one has to be mutable in any case.You misunderstand. The idea is this: void foo( ) { Object p; if ( m ) { p = new Object( ); p.DoSomethingThatNeedsToBeDoneNow( ); } // 20 lines of code here if ( m ) { p.doSomethingWeird( dataFromAbove ); } }You're right, the real cases where this kind of thing occurs are much more complex. I just posted the thing boiled down. And, of course, there's always a way to refactor the code to eliminate the spurious error message. But sometimes the result is as ugly as Pascal's efforts to prove you really don't need a 'break' statement in a loop. The real problem with the spurious errors is that then people will put in an initialization "just to shut the compiler up." Time passes, and the next guy is looking at the code and wonders why x is being initialized to a value that is apparently never used, or worse, is initialized to some bogus value randomly picked by the long-retired programmer. I've seen code reviewers losing a lot of time on this issue.
Nov 07 2010
That's why we have immutable variables. They force you to think what to put in the variables. A lot of cases like the one above would be solved if if-then-else was an functional expression instead of a void returning statement. C/C++/D has the ternary ?: but the syntax is obfuscated. Object p = if (m) { ... foo; } else { ... bar; } instead of Object p; if (m) { ... p = foo; } else { ... p = bar; } There are even cases where the former can be const. The latter one has to be mutable in any case.Not related to this but i have to share. Try compiling this in C/C++. int i = i + 5; // something like this. This compiles with no warning, no error, nothing... I have absolutely no idea how this thing survived so long. -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Nov 07 2010
so Wrote:Not related to this but i have to share. Try compiling this in C/C++. int i = i + 5; // something like this.void main() { int i = i + 5; // something like this. } Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. test.c c:\temp\test.c(3) : warning C4700: uninitialized local variable 'i' used
Nov 07 2010
"Jussi Jumppanen" <jussij zeuseedit.com> wrote in message news:ib84l5$205p$1 digitalmars.com...so Wrote:Well I'll be damned, even C/C++ knows that uninitialized variables shouldn't be used, and yet D doesn't. This is where Walter claims that getting rid of that warning improves safety because it prevents people from "shutting the compiler up" by changing this: int i = i + 5; Into this code which D happily accepts: int i; i = i + 5;Not related to this but i have to share. Try compiling this in C/C++. int i = i + 5; // something like this.void main() { int i = i + 5; // something like this. } Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. test.c c:\temp\test.c(3) : warning C4700: uninitialized local variable 'i' used
Nov 07 2010
Nick Sabalausky wrote:Well I'll be damned, even C/C++ knows that uninitialized variables shouldn't be used, and yet D doesn't. This is where Walter claims that getting rid of that warning improves safety because it prevents people from "shutting the compiler up" by changing this: int i = i + 5; Into this code which D happily accepts: int i; i = i + 5;For the code: void test() { int i = i + 5; } D reports: test.d(4): Error: undefined identifier i
Nov 07 2010
"Walter Bright" <newshound2 digitalmars.com> wrote in message news:ib87ai$26u8$1 digitalmars.com...Nick Sabalausky wrote:Yes, which by your "people will toss something in to shut the compiler up" reasoning will then cause people to turn that into this "to shut the compiler up": void test() { int i; i = i + 5; } Which the D compiler will be perfectly happy with even though it's probably wrong.Well I'll be damned, even C/C++ knows that uninitialized variables shouldn't be used, and yet D doesn't. This is where Walter claims that getting rid of that warning improves safety because it prevents people from "shutting the compiler up" by changing this: int i = i + 5; Into this code which D happily accepts: int i; i = i + 5;For the code: void test() { int i = i + 5; } D reports: test.d(4): Error: undefined identifier i
Nov 08 2010
Nick Sabalausky wrote:"Walter Bright" <newshound2 digitalmars.com> wrote in messageI see no reason why people would do that. It doesn't save typing, it isn't convenient, etc.For the code: void test() { int i = i + 5; } D reports: test.d(4): Error: undefined identifier iYes, which by your "people will toss something in to shut the compiler up" reasoning will then cause people to turn that into this "to shut the compiler up": void test() { int i; i = i + 5; } Which the D compiler will be perfectly happy with even though it's probably wrong.
Nov 08 2010
Walter Bright wrote:I see no reason why people would do that. It doesn't save typing, it isn't convenient, etc.What I mean is that I've never seen anyone do that, and I've seen a lot of junk people did to shut the compiler up.
Nov 08 2010
int i; i = i + 5;I can't see any uninitialized var there, can you? :P -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Nov 07 2010
"so" <so so.do> wrote in message news:op.vlubxy2a7dtt59 so-pc...There's no usage of an undeclared variable, but the right-hand-side of the second line uses 'i' before *the programmer* initializes it. Yes, the D compiler chooses to automatically initialize it, but by doing so it silently creates a bug every time the programmer intends 'i' to start out as anything other than 0. And it's not easily noticed since 0 is a commonly-used value. (Something like 0xDEADBEEF would at least be an improvement (albeit a small one) since at least that would stand out more and likely fail more spectacularly.)int i; i = i + 5;I can't see any uninitialized var there, can you? :P
Nov 08 2010
There's no usage of an undeclared variable, but the right-hand-side of the second line uses 'i' before *the programmer* initializes it. Yes, the D compiler chooses to automatically initialize it, but by doing so it silently creates a bug every time the programmer intends 'i' to start out as anything other than 0. And it's not easily noticed since 0 is a commonly-used value. (Something like 0xDEADBEEF would at least be an improvement (albeit a small one) since at least that would stand out more and likely fail more spectacularly.)So you want language force you to type either "int x=0;" or "int x=void;". Fair enough and i agree it "might" be a bit better. But you are making it as it is something so much important. Again, for both coder and the code-reader there is no ambiguity here, every single thing is defined. -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Nov 08 2010
"so" <so so.do> wrote in message news:op.vlv3iukp7dtt59 so-pc...I tend to get a bit fired up by it because Walter's reasoning on it being *better* to automatically assume some init value baffles me.There's no usage of an undeclared variable, but the right-hand-side of the second line uses 'i' before *the programmer* initializes it. Yes, the D compiler chooses to automatically initialize it, but by doing so it silently creates a bug every time the programmer intends 'i' to start out as anything other than 0. And it's not easily noticed since 0 is a commonly-used value. (Something like 0xDEADBEEF would at least be an improvement (albeit a small one) since at least that would stand out more and likely fail more spectacularly.)So you want language force you to type either "int x=0;" or "int x=void;". Fair enough and i agree it "might" be a bit better. But you are making it as it is something so much important.Again, for both coder and the code-reader there is no ambiguity here, every single thing is defined.Whether or not it's defined isn't really the issue here (although if it weren't defined, that would definitely be a problem). It just comes down to "more error-prone" vs "less error-prone".
Nov 08 2010
Nick Sabalausky schrieb:"so" <so so.do> wrote in message news:op.vlv3iukp7dtt59 so-pc...It gives deterministic results/errors. For example, when your code works when an int is initialized with 0 (but you didn't initialize it), it may work most of the time in C and fail randomly. In D it will always work. Same thing the other way round. Or if you do some calculation with an uninitialized int value.. I guess 0 is one of the easiest values to spot: on multiplication it creates 0 and on addition it doesn't change to value so by looking at the unwanted result of a calculation you probably can see the error more easily than on some other value (or even a random value, that may create results that look about right).I tend to get a bit fired up by it because Walter's reasoning on it being *better* to automatically assume some init value baffles me.There's no usage of an undeclared variable, but the right-hand-side of the second line uses 'i' before *the programmer* initializes it. Yes, the D compiler chooses to automatically initialize it, but by doing so it silently creates a bug every time the programmer intends 'i' to start out as anything other than 0. And it's not easily noticed since 0 is a commonly-used value. (Something like 0xDEADBEEF would at least be an improvement (albeit a small one) since at least that would stand out more and likely fail more spectacularly.)So you want language force you to type either "int x=0;" or "int x=void;". Fair enough and i agree it "might" be a bit better. But you are making it as it is something so much important.
Nov 09 2010
Daniel Gibson <metalcaedes gmail.com> wrote:Nick Sabalausky schrieb:Yup. Also, as opposed to certain other solutions, it does not require advanced flow control, that is likely to be incomplete. Incomplete flow control here will make people write code 'to shut the compiler up'. And that is worse than uninitialized variables. -- Simen"so" <so so.do> wrote in message news:op.vlv3iukp7dtt59 so-pc...It gives deterministic results/errors.I tend to get a bit fired up by it because Walter's reasoning on it being *better* to automatically assume some init value baffles me.There's no usage of an undeclared variable, but the right-hand-side of the second line uses 'i' before *the programmer* initializes it. Yes, the D compiler chooses to automatically initialize it, but by doing so it silently creates a bug every time the programmer intends 'i' to start out as anything other than 0. And it's not easily noticed since 0 is a commonly-used value. (Something like 0xDEADBEEF would at least be an improvement (albeit a small one) since at least that would stand out more and likely fail more spectacularly.)So you want language force you to type either "int x=0;" or "int x=void;". Fair enough and i agree it "might" be a bit better. But you are making it as it is something so much important.
Nov 09 2010
"Simen kjaeraas" <simen.kjaras gmail.com> wrote in message news:op.vlwul8tuvxi10f biotronic-pc.lan...Daniel Gibson <metalcaedes gmail.com> wrote:First of all, the risks from "shut the compiler up" initalizations are crap on the "dangers" of that). Secondly, there is absolutely no way it's worse than auto-initing. Let's look at an example: int i; // Dumb-ass convoluted code that should never pass code review anyway: if(m) i = something; // Stuff here if(m) // Do something with 'i' Suppose the compiler complains 'i' might be used before being written to. The programmer has two choices: 1. Blindly toss in "=0" with no regard as to whether or not it's correct. 2. Fix the damn code properly (And believe it or not, this *may* actually amount to "int i=0;", but just not always). Now, let's go back to D's current behavior. Only one thing ever happens now. The compiler will: 1. Blindly toss in "=0" with no regard as to whether or not it's correct. Note that's word-for-word identical to before, except now option 2, the *right* option, doesn't even fucking exist. That does NOT make it better, that makes it worse.Nick Sabalausky schrieb:Yup. Also, as opposed to certain other solutions, it does not require advanced flow control, that is likely to be incomplete. Incomplete flow control here will make people write code 'to shut the compiler up'. And that is worse than uninitialized variables."so" <so so.do> wrote in message news:op.vlv3iukp7dtt59 so-pc...It gives deterministic results/errors.I tend to get a bit fired up by it because Walter's reasoning on it being *better* to automatically assume some init value baffles me.There's no usage of an undeclared variable, but the right-hand-side of the second line uses 'i' before *the programmer* initializes it. Yes, the D compiler chooses to automatically initialize it, but by doing so it silently creates a bug every time the programmer intends 'i' to start out as anything other than 0. And it's not easily noticed since 0 is a commonly-used value. (Something like 0xDEADBEEF would at least be an improvement (albeit a small one) since at least that would stand out more and likely fail more spectacularly.)So you want language force you to type either "int x=0;" or "int x=void;". Fair enough and i agree it "might" be a bit better. But you are making it as it is something so much important.
Nov 09 2010
"Nick Sabalausky" <a a.a> wrote in message news:ibc5ve$1q75$1 digitalmars.com..."Simen kjaeraas" <simen.kjaras gmail.com> wrote in message news:op.vlwul8tuvxi10f biotronic-pc.lan...Also, as I've said when this was discussed in the past, I wouldn't even want the flow analysis to be perfect because all that would accomplish is to encourage garbage like the above (which would just end up being highly fragile anway).Yup. Also, as opposed to certain other solutions, it does not require advanced flow control, that is likely to be incomplete. Incomplete flow control here will make people write code 'to shut the compiler up'. And that is worse than uninitialized variables.First of all, the risks from "shut the compiler up" initalizations are crap on the "dangers" of that). Secondly, there is absolutely no way it's worse than auto-initing. Let's look at an example: int i; // Dumb-ass convoluted code that should never pass code review anyway: if(m) i = something; // Stuff here if(m) // Do something with 'i'Suppose the compiler complains 'i' might be used before being written to. The programmer has two choices: 1. Blindly toss in "=0" with no regard as to whether or not it's correct. 2. Fix the damn code properly (And believe it or not, this *may* actually amount to "int i=0;", but just not always). Now, let's go back to D's current behavior. Only one thing ever happens now. The compiler will: 1. Blindly toss in "=0" with no regard as to whether or not it's correct. Note that's word-for-word identical to before, except now option 2, the *right* option, doesn't even fucking exist. That does NOT make it better, that makes it worse.
Nov 09 2010
Nick Sabalausky <a a.a> wrote:Also, as I've said when this was discussed in the past, I wouldn't even want the flow analysis to be perfect because all that would accomplish is to encourage garbage like the above (which would just end up being highly fragile anway).But if it isn't, we must either define what it should do, or accept that some compilers will catch some of the uninitialized variable bugs, where others do not. We do not want that. -- Simen
Nov 09 2010
I agree with Nick Sabalausky in this discussion. Simen kjaeraas:But if it isn't, we must either define what it should do, or accept that some compilers will catch some of the uninitialized variable bugs, where others do not. We do not want that.Right. There are ways to write formal specs for this too But it's not an easy thing to do. D has chosen to have simpler implementation and specs. This means that on this regard implementing a correct D front-end is Bye, bearophile
Nov 09 2010
"Simen kjaeraas" <simen.kjaras gmail.com> wrote in message news:op.vlw3ohvavxi10f biotronic-pc.lan...Nick Sabalausky <a a.a> wrote:Agreed.Also, as I've said when this was discussed in the past, I wouldn't even want the flow analysis to be perfect because all that would accomplish is to encourage garbage like the above (which would just end up being highly fragile anway).But if it isn't, we must either define what it should do, or accept that some compilers will catch some of the uninitialized variable bugs, where others do not. We do not want that.
Nov 09 2010
"Daniel Gibson" <metalcaedes gmail.com> wrote in message news:ibbp25$ls8$1 digitalmars.com...Nick Sabalausky schrieb:Where are people getting the idea that I've said C's behavior is better than D's? Once again, I'm not talking about D vs C (ie "int i;" leaves 'i' in an compile-time errors when 'i' is read before being written to)."so" <so so.do> wrote in message news:op.vlv3iukp7dtt59 so-pc...It gives deterministic results/errors. For example, when your code works when an int is initialized with 0 (but you didn't initialize it), it may work most of the time in C and fail randomly. In D it will always work. Same thing the other way round. Or if you do some calculation with an uninitialized int value.. I guess 0 is one of the easiest values to spot: on multiplication it creates 0 and on addition it doesn't change to value so by looking at the unwanted result of a calculation you probably can see the error more easily than on some other value (or even a random value, that may create results that look about right).I tend to get a bit fired up by it because Walter's reasoning on it being *better* to automatically assume some init value baffles me.There's no usage of an undeclared variable, but the right-hand-side of the second line uses 'i' before *the programmer* initializes it. Yes, the D compiler chooses to automatically initialize it, but by doing so it silently creates a bug every time the programmer intends 'i' to start out as anything other than 0. And it's not easily noticed since 0 is a commonly-used value. (Something like 0xDEADBEEF would at least be an improvement (albeit a small one) since at least that would stand out more and likely fail more spectacularly.)So you want language force you to type either "int x=0;" or "int x=void;". Fair enough and i agree it "might" be a bit better. But you are making it as it is something so much important.
Nov 09 2010
"Nick Sabalausky" <a a.a> wrote in message news:ibc4h2$1mmn$1 digitalmars.com..."Daniel Gibson" <metalcaedes gmail.com> wrote in message news:ibbp25$ls8$1 digitalmars.com...Again, saying "Not giving compile-time errors on reading before writing is good because C leaves values in an undefined state" **makes no sense**. It's a complete non-sequitor.Nick Sabalausky schrieb:Where are people getting the idea that I've said C's behavior is better than D's? Once again, I'm not talking about D vs C (ie "int i;" leaves 'i' compile-time errors when 'i' is read before being written to)."so" <so so.do> wrote in message news:op.vlv3iukp7dtt59 so-pc...It gives deterministic results/errors. For example, when your code works when an int is initialized with 0 (but you didn't initialize it), it may work most of the time in C and fail randomly. In D it will always work. Same thing the other way round. Or if you do some calculation with an uninitialized int value.. I guess 0 is one of the easiest values to spot: on multiplication it creates 0 and on addition it doesn't change to value so by looking at the unwanted result of a calculation you probably can see the error more easily than on some other value (or even a random value, that may create results that look about right).I tend to get a bit fired up by it because Walter's reasoning on it being *better* to automatically assume some init value baffles me.There's no usage of an undeclared variable, but the right-hand-side of the second line uses 'i' before *the programmer* initializes it. Yes, the D compiler chooses to automatically initialize it, but by doing so it silently creates a bug every time the programmer intends 'i' to start out as anything other than 0. And it's not easily noticed since 0 is a commonly-used value. (Something like 0xDEADBEEF would at least be an improvement (albeit a small one) since at least that would stand out more and likely fail more spectacularly.)So you want language force you to type either "int x=0;" or "int x=void;". Fair enough and i agree it "might" be a bit better. But you are making it as it is something so much important.
Nov 09 2010
On Mon, 08 Nov 2010 08:17:09 +0200, Jussi Jumppanen <jussij zeuseedit.com> wrote:so Wrote:I am using VC++ Express 2008, and last time i tried warning level was either 3 or 4, nothing. It is not a simple uninitialized variable bug, it is a serious error. At initialization rvalue should not contain anything about lvalue, this is absurd. -- Using Opera's revolutionary email client: http://www.opera.com/mail/Not related to this but i have to share. Try compiling this in C/C++. int i = i + 5; // something like this.void main() { int i = i + 5; // something like this. } Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. test.c c:\temp\test.c(3) : warning C4700: uninitialized local variable 'i' used
Nov 07 2010
so Wrote:At initialization rvalue should not contain anything about lvalue, this is absurd.That may well be the case. I was only pointing out that as far as the Microsoft compiler is concerned, saying the code: 'compiles with no warning, no error, nothing...' is incorrect. It will issue a warning even if the default warning level of 1 is used. Now as to question whether or not this is a smart way to handle the situation, that is a totally different discussion all together;)
Nov 08 2010
"Walter Bright" <newshound2 digitalmars.com> wrote in message news:ib783u$1odt$1 digitalmars.com...The real problem with the spurious errors is that then people will put in an initialization "just to shut the compiler up." Time passes, and the next guy is looking at the code and wonders why x is being initialized to a value that is apparently never used, or worse, is initialized to some bogus value randomly picked by the long-retired programmer. I've seen code reviewers losing a lot of time on this issue. In general, I am opposed to inserting dead code and unused values to get the compiler to accept the program.Yes, you'd rather silently insert a value even when it's the wrong value.
Nov 07 2010
"Jonathan M Davis" <jmdavisProg gmx.com> wrote in message news:mailman.144.1289103661.21107.digitalmars-d puremagic.com...On Saturday 06 November 2010 19:05:32 Nick Sabalausky wrote:The problem is values accidentally not being inited. When that happens, D jumps in and just assumes it should be xxxx, which is not always correct. "null" is not always the intended starting value for a reference type. 0 is not always the intended starting value for an integer type. Invalid-code-unit is not always the intended starting value for a character. NaN is not always the intended starting value for a floating point type, and while it *is* better than, for example, 0 for ints, it's still tends to leave the error undetected until further down the code-path (same for null)."foobar" <foo bar.com> wrote in messagend in a pointlessly roundabout way.Now, it may be that declaring variables without initializing them (which generally should be avoided regardless), it generally doesn't matter.2. "null" is an a type-system attribute, hence should be checked at compile time and would have ZERO affect on run-time performance. Same as assigning a string value to an int variable.I strongly agree with this. On a related note, I *hate* that D silently sticks in a default value whenever anything isn't properly inited. This is one thing where I really leaving it with an undefined value like C does!" banner is an irritating strawman: Yea, it's better than C, but it still sucks.Also, it's essentially D's stance that not initializing a variable is a bug, so every variable is default initialized to the closest to an error value that exists for that type.So why respond to a bug by ignoring it and occasionally turning it into another bug? If it considers something a bug, then it should *say* so.It's not at all inconsistent if you look at from the perspective that types are default initialized to the closest thing to an error value that they have. Many of the value types (such as the integral types), don't really have a value that's an obvious error, so they don't fit in with that quite so well, but it's unavoidable given that they just don't have an obvious error value.See, that goes back to what the OP was saying, and I agree with: "Error" should *not* be a valid value for a type (unless explicitly decreed by the programmer for a specific variable). It should either be a value that the programmer explicitly *gives* it, or a compile-time error.And I don't understand why you think that nullability shouldn't be a difference between value types and reference types. That's one of the _key_ differences between them. Value types _cannot_ be null, while references can. And I'd sure hate to _not_ be able to have a null reference.It's only a difference in D because D makes it so. It's *not* a fundamental difference of the concept of a "reference type" and "value type". Non-nullable reference types can and do exist. And Haxe has value types that are nullable. I thnk JS does too. And I never suggested we not be able to have null references at all. In fact, I already made a big point that they *should* be allowed: "there are plenty of cases where run-time nullability is useful and where lack of it is problematic at best: A tree or linked list, for example. The "null object" idiom doesn't count, because all it does is just reinvent null, and in a pointlessly roundabout way." It just shouldn't be default, and it should only be used when it's actually needed.I can totally understand wanting non-nullable reference types. There are plenty of times where it just doesn't make sense to a have a variable which can be null - even if it's a reference - but there are plenty of cases where it _does_ make sense,Agreed. And I've also come across plenty of cases where nullable value types are useful (but obviously they shouldn't be the default). Conceptually, nullability is orthogonal from reference-vs-value, but many languages conflate the two (presumably because it just happens to be the easiest due to the way the hardware typically works).
Nov 07 2010
Jonathan M Davis Wrote:On Saturday 06 November 2010 19:05:32 Nick Sabalausky wrote:Ideally you should have TWO types: T and Option!T (ignore syntax for now). Most of the time you would use: auto variable = new T(params); // no need for nulls here! and for the situations where you actually NEED to have a non-initialized variable you'd use: Option!T variable; // look ma, explicitly asking for a nullable variable Simple, ain't it? And it supports Walter's convoluted examples AND is explicit about it so it prevents illegal operations at compile time."foobar" <foo bar.com> wrote in messagend in a pointlessly roundabout way.initialize variables even in cases where they know that it's not necessary (which is annoying but may or may not be worth it), but more importantly (from Walter's perspective at least), it would require flow analysis, which he actively avoids. Using default values avoids memory bugs like you get in C and results in a simpler compiler implementation (and therefore a less bug-prone one) and makes it simpler for other tools to be written for the language. Now, it may be that declaring variables without initializing them (which generally should be avoided regardless), it generally doesn't matter. Also, it's essentially D's stance that not initializing a variable is a bug, so every variable is default initialized to the closest to an error value that exists for that type. null is the obvious choice for pointers and references. I'm moderately divided on the issue, but ultimately, I think that D's decision what D does works quite well.2. "null" is an a type-system attribute, hence should be checked at compile time and would have ZERO affect on run-time performance. Same as assigning a string value to an int variable.I strongly agree with this. On a related note, I *hate* that D silently sticks in a default value whenever anything isn't properly inited. This is one thing where I really it with an undefined value like C does!" banner is an irritating strawman: Yea, it's better than C, but it still sucks.I also dislike that D's reference types being nullable by default is inconsistent with its value types. (Yea, naturally reference and value types are going to have inherent differences, but nullability shouldn't be one of them.)It's not at all inconsistent if you look at from the perspective that types are default initialized to the closest thing to an error value that they have. Many of the value types (such as the integral types), don't really have a value that's an obvious error, so they don't fit in with that quite so well, but it's unavoidable given that they just don't have an obvious error value. And I don't understand why you think that nullability shouldn't be a difference between value types and reference types. That's one of the _key_ differences between them. Value types _cannot_ be null, while references can. And I'd sure hate to _not_ be able to have a null reference. It's irritating enough that arrays and associative arrays are almost treated the same when they're null as when they're empty. I can totally understand wanting non-nullable reference types. There are plenty of times where it just doesn't make sense to a have a variable which can be null - even if it's a reference - but there are plenty of cases where it _does_ make sense, and I do find the fact that D default initializes to error values to be quite useful, since I do consider it bad practice in general to not initialize a variable when it's declared. Sometimes you have to for scoping reasons or whatnot, but generally, variables _should_ be initialized when declared. - Jonathan M Davis
Nov 07 2010
On Sun, 07 Nov 2010 07:20:10 -0500 foobar <foo bar.com> wrote:Simple, ain't it? And it supports Walter's convoluted examples AND is exp=licit about it so it prevents illegal operations at compile time. ... AND it makes to safe case default ;-) Denis -- -- -- -- -- -- -- vit esse estrany =E2=98=A3 spir.wikidot.com
Nov 07 2010
On Sunday 07 November 2010 04:20:10 foobar wrote:Ideally you should have TWO types: T and Option!T (ignore syntax for now). Most of the time you would use: auto variable = new T(params); // no need for nulls here! and for the situations where you actually NEED to have a non-initialized variable you'd use: Option!T variable; // look ma, explicitly asking for a nullable variable Simple, ain't it? And it supports Walter's convoluted examples AND is explicit about it so it prevents illegal operations at compile time.Making non-nullable the default would be a seriously breaking change and obviously contradict TDPL. So, I don't see that ever changing. Adding non- nullable support to the language could be done - it's likely to be an additive change and wouldn't break any code - but making them the default? Not going to happen. _Maybe_ if D3 ever materializes, it could happen then, but it would break a lot of code. - Jonathan M Davis
Nov 07 2010
foobar Wrote:Jonathan M Davis Wrote:Sounds more retarded than the notorious 'retard' here. It's because of people like u that D3 might not come. If you disagree too much with AA and WB they have no interest to make D3. This nonnull question might be good place to give up.On Saturday 06 November 2010 19:05:32 Nick Sabalausky wrote:Ideally you should have TWO types: T and Option!T (ignore syntax for now). Most of the time you would use: auto variable = new T(params); // no need for nulls here! and for the situations where you actually NEED to have a non-initialized variable you'd use: Option!T variable; // look ma, explicitly asking for a nullable variable Simple, ain't it? And it supports Walter's convoluted examples AND is explicit about it so it prevents illegal operations at compile time."foobar" <foo bar.com> wrote in messagend in a pointlessly roundabout way.initialize variables even in cases where they know that it's not necessary (which is annoying but may or may not be worth it), but more importantly (from Walter's perspective at least), it would require flow analysis, which he actively avoids. Using default values avoids memory bugs like you get in C and results in a simpler compiler implementation (and therefore a less bug-prone one) and makes it simpler for other tools to be written for the language. Now, it may be that declaring variables without initializing them (which generally should be avoided regardless), it generally doesn't matter. Also, it's essentially D's stance that not initializing a variable is a bug, so every variable is default initialized to the closest to an error value that exists for that type. null is the obvious choice for pointers and references. I'm moderately divided on the issue, but ultimately, I think that D's decision what D does works quite well.2. "null" is an a type-system attribute, hence should be checked at compile time and would have ZERO affect on run-time performance. Same as assigning a string value to an int variable.I strongly agree with this. On a related note, I *hate* that D silently sticks in a default value whenever anything isn't properly inited. This is one thing where I really it with an undefined value like C does!" banner is an irritating strawman: Yea, it's better than C, but it still sucks.I also dislike that D's reference types being nullable by default is inconsistent with its value types. (Yea, naturally reference and value types are going to have inherent differences, but nullability shouldn't be one of them.)It's not at all inconsistent if you look at from the perspective that types are default initialized to the closest thing to an error value that they have. Many of the value types (such as the integral types), don't really have a value that's an obvious error, so they don't fit in with that quite so well, but it's unavoidable given that they just don't have an obvious error value. And I don't understand why you think that nullability shouldn't be a difference between value types and reference types. That's one of the _key_ differences between them. Value types _cannot_ be null, while references can. And I'd sure hate to _not_ be able to have a null reference. It's irritating enough that arrays and associative arrays are almost treated the same when they're null as when they're empty. I can totally understand wanting non-nullable reference types. There are plenty of times where it just doesn't make sense to a have a variable which can be null - even if it's a reference - but there are plenty of cases where it _does_ make sense, and I do find the fact that D default initializes to error values to be quite useful, since I do consider it bad practice in general to not initialize a variable when it's declared. Sometimes you have to for scoping reasons or whatnot, but generally, variables _should_ be initialized when declared. - Jonathan M Davis
Nov 07 2010
On Sun, 07 Nov 2010 18:01:32 +0300, steveh <steveh57 hotmai.l> wrote:Sounds more retarded than the notorious 'retard' here. It's because of people like u that D3 might not come. If you disagree too much with AA and WB they have no interest to make D3. This nonnull question might be good place to give up.Cool down and relax! His post wasn't actually that bad.
Nov 07 2010
On 11/7/10 9:08 AM, Denis Koroskin wrote:On Sun, 07 Nov 2010 18:01:32 +0300, steveh <steveh57 hotmai.l> wrote:Clearly it is the preference of some that non-null references are the default (so then one can use e.g. an option datatype to model nullable references). It is also the preference of some that values are immutable by default. I think it's too late to change such defaults at this point. I think it's reasonable to let the current references and pointers continue to be as they are, and work on disable (particularly its interaction with constructors) to make it easy to implement restricted subsets of values. Then NonNull would be a useful library artifact among other ones. AndreiSounds more retarded than the notorious 'retard' here. It's because of people like u that D3 might not come. If you disagree too much with AA and WB they have no interest to make D3. This nonnull question might be good place to give up.Cool down and relax! His post wasn't actually that bad.
Nov 07 2010
I think it's reasonable to let the current references and pointers continue to be as they are, and work on disable (particularly its interaction with constructors) to make it easy to implement restricted subsets of values. Then NonNull would be a useful library artifact among other ones. AndreiRather than focusing solely at NonNull, I'd prefer to return to the problem at hand and ask what alternate solutions are there? For that reason I really like Andrei's approach, as it has far wider appliances. Still I'd like to point out one other idea which I came across in the programming language 'E', it's extemely simple to implement yet solves many other problems which nonnull cannot. http://blubbedev.net/e_guide_html/ch_13c.html As I see it, the main problem is interoperability between 3rd party libraries... in contrast to within ones own framwork/program since 'D' already provides first class error handling mechanisms. Basically it's just a "global" list of "function error return codes" translated into the exception of your choice, sure it is possible to wrap everything manually... but this mechanism makes it very easy to do the right thing and _keep_ the old naming convention of the 3rd party library and still benefit from improved automatic error handling... Teoretically one could specify it already when importing the function with "extern C" etc... but it probably would require too many manual adjustments to be really useful... well just _throwing_ the idea in here. ;) Wyrlon
Nov 07 2010
"steveh" <steveh57 hotmai.l> wrote in message news:ib6f0c$2s4o$1 digitalmars.com...Sounds more retarded than the notorious 'retard' here. It's because of people like u that D3 might not come. If you disagree too much with AA and WB they have no interest to make D3. This nonnull question might be good place to give up.Ridiculous argument. Even if Walter and Andrei were that petty (they're not), then not pushing important changes like this would render any D3 pointless anyway.
Nov 07 2010
Nick Sabalausky Wrote:"foobar" <foo bar.com> wrote in message news:ib3a8k$1i58$1 digitalmars.com...You seem to contradict yourself a bit here. As you pointed out yourself bellow, if you really *want* to use nullable types than you should explicitly use option!T instead of T. This is how those data structures you mentioned are implemented in languages such as ML. e.g. datatype Tree = Leaf | Tree of ('a * Tree * Tree) usage example: fun sum Leaf = 0 | sum Tree(val, left , right) = val + sum (left) + sum (right) The important point here is that it won't COMPILE without the first part that handles the Leaf. This makes the use of null explicit and the compiler will verify that you are using nulls correctly. In current D, there is no check to prevent compiling of: int sum(Tree tree) { // doesn't handle case of null tree !!! return tree.value + sum(tree.left) + sum(tree.right); } This is not the OO null object idiom and there's no re-invention of null here since I haven't discussed the implementation of Option(T) at all. IMO it should be a language built-in just like const is in order to get the full benefits like in ML.1. the INVENTOR of the "reference" concept himself admits that this is a flawed design. see: http://qconlondon.com/london-2009/presentation/Null+References:+The+Billion+Dollar+MistakeFirst of all, "appeal to authority" is a logical fallacy. Second, there are plenty of cases where run-time nullability is useful and where lack of it is problematic at best: A tree or linked list, for example. The "null object" idiom doesn't count, because all it does is just reinvent null, and in a pointlessly roundabout way.2. "null" is an a type-system attribute, hence should be checked at compile time and would have ZERO affect on run-time performance. Same as assigning a string value to an int variable.I strongly agree with this. On a related note, I *hate* that D silently sticks in a default value whenever anything isn't properly inited. This is one thing where I really it with an undefined value like C does!" banner is an irritating strawman: Yea, it's better than C, but it still sucks. I also dislike that D's reference types being nullable by default is inconsistent with its value types. (Yea, naturally reference and value types are going to have inherent differences, but nullability shouldn't be one of them.)3. the notion of an "undefined" state for a type can be generally implemented by the OPTION type and D pointers are an ad hoc implementation of this concept. see: http://en.wikipedia.org/wiki/Option_type Any type can be wrapped by an OPTION type. trying to do the converse of this is impractical and is bad design.I strongly agree with this, too.4. As already pointed by others, Walter's array should be: Option!T[] array;Only if you actually *want* to allow null elements.5. C programmers use null pointers and other special "canary" values as Walter described mainly as rcodes. This is a BAD and bug-prone way of handling errors and is replaced in D by a MUCH better mechanism called "Exceptions".Absolutely agree.
Nov 07 2010
"foobar" <foo bar.com> wrote in message news:ib5l2a$1v9$1 digitalmars.com...Nick Sabalausky Wrote:It's been awhile since I read that article you linked to, but from what I remember, it sounded to me like he was saying that nullability period was bad, and that there should never be any nulls (but maybe I'm just misremembering). So I thought you were also saying that there should not be any nullability."foobar" <foo bar.com> wrote in message news:ib3a8k$1i58$1 digitalmars.com...You seem to contradict yourself a bit here.1. the INVENTOR of the "reference" concept himself admits that this is a flawed design. see: http://qconlondon.com/london-2009/presentation/Null+References:+The+Billion+Dollar+MistakeFirst of all, "appeal to authority" is a logical fallacy. Second, there are plenty of cases where run-time nullability is useful and where lack of it is problematic at best: A tree or linked list, for example. The "null object" idiom doesn't count, because all it does is just reinvent null, and in a pointlessly roundabout way.As you pointed out yourself bellow, if you really *want* to use nullable types than you should explicitly use option!T instead of T.Yup, I think we completely agree on everything here.
Nov 07 2010
On a related note, I *hate* that D silently sticks in a default value whenever anything isn't properly inited. This is one thing where I really leaving it with an undefined value like C does!" banner is an irritating strawman: Yea, it's better than C, but it still sucks.This is one of the times (and this doesn't happen rarely) i am glad Walter is the head of D. It is total BS i am sorry can put it in a polite way. -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Nov 07 2010
"so" <so so.do> wrote in message news:op.vls71ytk7dtt59 so-pc...How is it total BS?On a related note, I *hate* that D silently sticks in a default value whenever anything isn't properly inited. This is one thing where I really leaving it with an undefined value like C does!" banner is an irritating strawman: Yea, it's better than C, but it still sucks.This is one of the times (and this doesn't happen rarely) i am glad Walter is the head of D. It is total BS i am sorry can put it in a polite way.
Nov 07 2010
On Sun, 07 Nov 2010 22:41:41 +0200, Nick Sabalausky <a a.a> wrote:"so" <so so.do> wrote in message news:op.vls71ytk7dtt59 so-pc...If a language is able to avoid bugs caused by uninitialized variables, it should. But when it comes to a system language you have to preserve the rights of those that know initialization is very expensive/or just plain unnecessary at some point, and want compiler to ignore it. "something a = void;" is a very elegant solution, and it is explicit, you have best of both worlds. You could have just argued about that explicit initialization should be a must, that would make sense in another language but D way is much better. You have both explicit initialization and default initialization since you know "int i" is "int i=0" at the instant you are typeing, same goes for reader of your code. -- Using Opera's revolutionary email client: http://www.opera.com/mail/How is it total BS?On a related note, I *hate* that D silently sticks in a default value whenever anything isn't properly inited. This is one thing where I really leaving it with an undefined value like C does!" banner is an irritating strawman: Yea, it's better than C, but it still sucks.This is one of the times (and this doesn't happen rarely) i am glad Walter is the head of D. It is total BS i am sorry can put it in a polite way.
Nov 07 2010
"so" <so so.do> wrote in message news:op.vltk19pq7dtt59 so-pc...On Sun, 07 Nov 2010 22:41:41 +0200, Nick Sabalausky <a a.a> wrote:Yes, and that is *exactly* why I've been saying the compiler should *track* whether or not something has been inited and then bitch when it's used without ebing inited, instead of just blindly tossing a '0' (or null, or NaN) in there with absolutely no knowledge whatsoever as to whether or not it actually *should* be starting out at '0' (or null, or NaN)."so" <so so.do> wrote in message news:op.vls71ytk7dtt59 so-pc...If a language is able to avoid bugs caused by uninitialized variables, it should.How is it total BS?On a related note, I *hate* that D silently sticks in a default value whenever anything isn't properly inited. This is one thing where I really leaving it with an undefined value like C does!" banner is an irritating strawman: Yea, it's better than C, but it still sucks.This is one of the times (and this doesn't happen rarely) i am glad Walter is the head of D. It is total BS i am sorry can put it in a polite way.But when it comes to a system language you have to preserve the rights of those that know initialization is very expensive/or just plain unnecessary at some point, and want compiler to ignore it. "something a = void;" is a very elegant solution, and it is explicit, you have best of both worlds.Uhh, yea, but what the hell does that have to do with what I said?
Nov 07 2010
"Nick Sabalausky" <a a.a> wrote in message news:ib84bo$1vcn$1 digitalmars.com..."so" <so so.do> wrote in message news:op.vltk19pq7dtt59 so-pc...issues a compile-time error whenever a variable is read before it's guaranteed to have been written (at least for local vars, I don't remember how it handles member vars).On Sun, 07 Nov 2010 22:41:41 +0200, Nick Sabalausky <a a.a> wrote:Yes, and that is *exactly* why I've been saying the compiler should *track* whether or not something has been inited and then bitch when it's used without ebing inited, instead of just blindly tossing a '0' (or null, or NaN) in there with absolutely no knowledge whatsoever as to whether or not it actually *should* be starting out at '0' (or null, or NaN)."so" <so so.do> wrote in message news:op.vls71ytk7dtt59 so-pc...If a language is able to avoid bugs caused by uninitialized variables, it should.How is it total BS?On a related note, I *hate* that D silently sticks in a default value whenever anything isn't properly inited. This is one thing where I really leaving it with an undefined value like C does!" banner is an irritating strawman: Yea, it's better than C, but it still sucks.This is one of the times (and this doesn't happen rarely) i am glad Walter is the head of D. It is total BS i am sorry can put it in a polite way.But when it comes to a system language you have to preserve the rights of those that know initialization is very expensive/or just plain unnecessary at some point, and want compiler to ignore it. "something a = void;" is a very elegant solution, and it is explicit, you have best of both worlds.Uhh, yea, but what the hell does that have to do with what I said?
Nov 07 2010
issues a compile-time error whenever a variable is read before it's guaranteed to have been written (at least for local vars, I don't remember how it handles member vars).That too, and i am having hard time understanding the other as well, that i thought you mean "int x;" can cause bugs but not "int x=0;" and compiler should track "int x;" -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Nov 07 2010
"so" <so so.do> wrote in message news:op.vlua80b47dtt59 so-pc...Example: // Returns: Needs another pass? bool process(ref int a) {...} // Process arr in reverse order. // Certain elements may need more than one pass. void foo(int[] arr) { int i; // Oops! Meant "int i = arr.length;" while(i > 0) { bool shouldReprocess = process(arr[i]); if(!shouldReprocess) i--; } } Yes, there are probably other ways to write that, but the basic idea is that bugs can be caused by D's automatically assuming you wanted to initialize to a certain value. Requiring you to actually say what value you want to start with would give the programmer a chance to avoid these problems. Walter is worried that this would cause certain programmers to blindly toss in something like "= 0". I say, if that's a bad thing to do, then why in the world should the compiler AUTOMATE that exact same bad idea?issues a compile-time error whenever a variable is read before it's guaranteed to have been written (at least for local vars, I don't remember how it handles member vars).That too, and i am having hard time understanding the other as well, that i thought you mean "int x;" can cause bugs but not "int x=0;" and compiler should track "int x;"
Nov 08 2010
Nick Sabalausky:still a hell of a lot better than "wrong", which is what D does (as evidenced by my first example above).I think all you have written in this post is correct. In this regard D is enough" here. A language "works" or fail for the whole ecosystem of its features. This means that even if a language has a less safe feature, other parts of the language may be able to compensate for it. This means that even if D default initialization may lead to some troubles, some other features may be enough to cover and avoid those problems. Well implemented nonnull types may be one of such patching features. But keep in mind that it's not easy to implement well nonnull types in an OOP language. They do have some corner cases (collection initialization is just one of them), that must be faced. The good thing is that other people have already found such corner cases and have invented "good" solution for them, so it's a matter of understanding them and then implementing it. In this thread I have seen discussed only about 1/3 of the corner cases and troubles needed to implement nonull types well enough. This paper contains the solution of about 1/4 of the problems, that may require a notDelayed attribute (the other problems are collection initialization and simplified typestate management): http://research.microsoft.com/apps/pubs/default.aspx?id=67979 Also, keep in mind that while default initialization of variables was adopted in D to avoid flow analysis, if you want to implement nonnull types "well enough" you need a simplified form of flow analysis again. I have explained why both in my bug report and in some answers in this thread. If there is some vague interest in adding nonnull types to D3, then this discussion has to become much less noisy and more focused on how to solve those "corner cases" (answer: probably copying the solutions already invented). Bye, bearophile
Nov 07 2010
"bearophile" <bearophileHUGS lycos.com> wrote in message news:ib6fuj$3j6$1 digitalmars.com...This paper contains the solution of about 1/4 of the problems, that may require a notDelayed attribute (the other problems are collection initialization and simplified typestate management): http://research.microsoft.com/apps/pubs/default.aspx?id=67979I only read the overview on that page, but it sounds like that could just be handled with ML-style nullable ("Option") types like foobar and I have suggested. Am I missing something? (I guess maybe I should just read the PDF :) ) Also, I'm curious what you mean by "collection initialization" and "simplified typestate management".
Nov 07 2010
Nick Sabalausky:Also, I'm curious what you mean by "collection initialization" and "simplified typestate management".Collections, like an array, need a temporary transient state where they may contain nulls too. The simple typestate management means that if you want to implement nonnull types well, the type system need to see the type of a variable as nullable in a point of the code, and nonnull later. The presence of an if statement or assert or cast needs to change the state of the type of the variable. I have explained a bit both things several times in posts. The problem with collections and the typestate needs are explained in the original little Bye, bearophile
Nov 07 2010