digitalmars.D.learn - Keyword to avoid not null references
- Namespace (24/24) Apr 21 2012 My question is, why D hasn't got an explicit Keyword to check at
- Adam D. Ruppe (3/3) Apr 21 2012 We can do not null in the library reasonably
- Namespace (13/16) Apr 21 2012 So every time i want to avoid null references i have to write
- Timon Gehr (8/26) Apr 21 2012 You might have a wrong mental model of how classes and structs work in D...
- Adam D. Ruppe (18/28) Apr 21 2012 It is already a reference! Otherwise, it couldn't be null anyway.
- Namespace (2/2) Apr 21 2012 I see you're right. Great! But it is only on git hub and not in
- Namespace (4/6) Apr 21 2012 But one thing: i missed there an invariant which check if t is
- Adam D. Ruppe (3/6) Apr 21 2012 Don't do that!
- Adam D. Ruppe (9/9) Apr 21 2012 I just pushed an update to git with
- Namespace (20/29) Apr 22 2012 Great work, but strange that the invariant break the whole code.
- Namespace (11/12) Apr 22 2012 But if the struct is in a separate module you get an error.
- Namespace (11/17) Apr 22 2012 I didn't recognized this part until now.
- Namespace (21/21) Apr 23 2012 I made several tests with NotNull yesterday and actually they all
- Simen Kjaeraas (4/24) Apr 23 2012 No. The whole point of NotNull is that it should enforce not being null.
- Dmitry Olshansky (5/40) Apr 23 2012 Just include obligatory run-time check when crossing null-NotNull
- Simen Kjaeraas (6/47) Apr 23 2012 Which carries with it hidden runtime costs that are unacceptable to some...
- Namespace (4/61) Apr 23 2012 Allow both: a type for explicit not null which cannot be changed
- Namespace (3/7) Apr 23 2012 Then i'm further for a keyword that checks an object for not null.
- Benjamin Thaut (19/39) Apr 23 2012 If you replace
- Namespace (18/71) Apr 23 2012 Yes, that's what i wrote a site before. Otherwise you couldn't
- Adam D. Ruppe (9/15) Apr 23 2012 The idea is to use NotNull!T to store your stuff,
- Namespace (7/22) Apr 23 2012 So if i wouldn't want such annoying debugging for a simple error
- Adam D. Ruppe (18/26) Apr 23 2012 No, I think that's too annoying, though I also think
- Adam D. Ruppe (2/4) Apr 21 2012 Right, I missed the deadline for that.
- bearophile (10/16) Apr 21 2012 I think before putting something in Phobos it's generally better
- Adam D. Ruppe (7/12) Apr 21 2012 I agree, but this comes up a LOT on the newsgroup,
- Jesse Phillips (31/34) Apr 22 2012 I'm thinking those interested in not null will want something
- Adam D. Ruppe (28/32) Apr 23 2012 Yeah, I like this idea, though a lot of what I do
- Timon Gehr (17/40) Apr 21 2012 It shouldn't be a special keyword. If the compiler can do the necessary
My question is, why D hasn't got an explicit Keyword to check at compile time for non null references? I understand that such check when they're implicit and refer to all objects they slow down the programm, but why doesn't exist an explicit keyword like ref or a simple ' ' before the Object name or value. Right now it's very annoying because i get a cryptical error message "Access violation" without any further informations and I have to debug. Only that way I can find where the Null references would access and then, why _and_ where the null references came from. That sucks. I hate it and so i write in every method to avoid null references "assert(obj !is null);". Now i get an assertion if obj is null and also the file and line. 50% less work then before. But it's still a runtime error and explicit work which can easily be checked by the compiler at compile time. Then i know: "oh there are null references and there shouldn't be any". So what are the reasons against a special keyword to let the compiler check for non references? I didn't understood it. I heard similar did implement something for that? Some variants I have already seen: const Foo obj, const Foo obj or my favourite: const ref Foo obj. Greetz
Apr 21 2012
We can do not null in the library reasonably well. I have a basic one in github: https://github.com/D-Programming-Language/phobos/pull/477
Apr 21 2012
On Saturday, 21 April 2012 at 22:18:02 UTC, Adam D. Ruppe wrote:We can do not null in the library reasonably well. I have a basic one in github: https://github.com/D-Programming-Language/phobos/pull/477So every time i want to avoid null references i have to write "NotNull!(Foo) f" (or better, because it's a struct: "ref NotNull!(Foo) f")? And therefore i must initialize them with NotNull!(Foo) f = new Foo();? That would be a little annoying. What if i needed in function bar only Foo f which can be null but in quatz i need a not null Reference? In my opinion the best way would be to initialize them with Foo f = new Foo(); and if i pass them to bar, it will be implicit cast to NotNull!(Foo). I think, that would be the best idea. The only thing that disturbing me, is, that it is a struct and therefore it passes by value instead as reference and that it is more to write as just " " or " ref".
Apr 21 2012
On 04/22/2012 12:48 AM, Namespace wrote:On Saturday, 21 April 2012 at 22:18:02 UTC, Adam D. Ruppe wrote:But this implies a runtime check.We can do not null in the library reasonably well. I have a basic one in github: https://github.com/D-Programming-Language/phobos/pull/477So every time i want to avoid null references i have to write "NotNull!(Foo) f" (or better, because it's a struct: "ref NotNull!(Foo) f")? And therefore i must initialize them with NotNull!(Foo) f = new Foo();? That would be a little annoying. What if i needed in function bar only Foo f which can be null but in quatz i need a not null Reference? In my opinion the best way would be to initialize them with Foo f = new Foo(); and if i pass them to bar, it will be implicit cast to NotNull!(Foo).I think, that would be the best idea. The only thing that disturbing me, is, that it is a struct and therefore it passes by value instead as referenceYou might have a wrong mental model of how classes and structs work in D. A class reference is much like a struct of the following form: struct ClassRef{ ClassImpl* impl; }and that it is more to write as just " " or " ref".And only the trivial cases are catched during compilation.
Apr 21 2012
On Saturday, 21 April 2012 at 22:48:27 UTC, Namespace wrote:So every time i want to avoid null references i have to write "NotNull!(Foo) f" (or better, because it's a struct: "ref NotNull!(Foo) f")?It is already a reference! Otherwise, it couldn't be null anyway. But, yes, you'd write NotNull!Foo. If "NotNull" is too long for you, you could always alias it to something else. alias NotNull n; n!Foo f; whatever floats your boat.And therefore i must initialize them with NotNull!(Foo) f = new Foo();? That would be a little annoying.If you don't initialize it, it would be null... so yes, you have to initialize it.What if i needed in function bar only Foo f which can be null but in quatz i need a not null Reference?If it can be null, you check for null or assume it isn't and just pass it straight to NotNull. One of the pull request comments suggests adding assumeNotNull and checkNotNull to help with this. I'll add that later.In my opinion the best way would be to initialize them with Foo f = new Foo(); and if i pass them to bar, it will be implicit cast to NotNull!(Foo).An implicit cast to not null would defeat the point of the new type! It implicitly casts to the regular (nullable) type, but going from null to not null implicitly means you have no help in catching it from the type system.
Apr 21 2012
I see you're right. Great! But it is only on git hub and not in the standard typecons header in 2.059, right?
Apr 21 2012
On Saturday, 21 April 2012 at 23:18:40 UTC, Namespace wrote:I see you're right. Great! But it is only on git hub and not in the standard typecons header in 2.059, right?But one thing: i missed there an invariant which check if t is null. If i write "f.t = null;" no error occured.
Apr 21 2012
On Saturday, 21 April 2012 at 23:27:38 UTC, Namespace wrote:But one thing: i missed there an invariant which check if t is null. If i write "f.t = null;" no error occured.Don't do that! Maybe I should make t private...
Apr 21 2012
I just pushed an update to git with a few changes people have suggested. I removed one of the old opAssigns to keep a static type check. Added assumeNotNull and checkNotNull as entry points. Made the data member private. I think that's closer to what everyone wants.
Apr 21 2012
On Sunday, 22 April 2012 at 00:06:47 UTC, Adam D. Ruppe wrote:I just pushed an update to git with a few changes people have suggested. I removed one of the old opAssigns to keep a static type check. Added assumeNotNull and checkNotNull as entry points. Made the data member private. I think that's closer to what everyone wants.Great work, but strange that the invariant break the whole code. Has anyone here an idea, how a implicit cast can work? Something like that should work: void foo(Foo f) { } void bar(NotNull!(Foo) f) { } Foo f = new Foo(); foo(f); bar(f); At the moment you must do it with bar(assumeNotNull(f)); and so you have twice as much work as actually being necessary. So in my opinion it must exist a way to avoid a explicit "cast" with assumeNotNull(f) on the caller side. Otherwise a check with assert(obj !is null); before you pass it to the method and then in the method again would do the same, and it's the same overhead. I think without the possibility to "cast" Foo without any explicit function call to NotNull!(Foo), there are not much advantages. What do you say?
Apr 22 2012
On Sunday, 22 April 2012 at 00:06:47 UTC, Adam D. Ruppe wrote:Made the data member private.But if the struct is in a separate module you get an error. So you must write T get() { return this._notNullData; } alias get this; instead alias _notNullData this; /// this is substitutable for the regular (nullable) type
Apr 22 2012
On Sunday, 22 April 2012 at 00:06:47 UTC, Adam D. Ruppe wrote:I just pushed an update to git with a few changes people have suggested. I removed one of the old opAssigns to keep a static type check. Added assumeNotNull and checkNotNull as entry points.I didn't recognized this part until now. The opAssign is still there and that's good. If i got you right on git, you wouldn't allow something like this: NotNull!(Foo) f = new Foo(); and instead you want that everybody writes NotNull!(Foo) f = assumeNotNull(new Foo); Is that correct? If so, that would increase the annoying factor which is still there because of the explicit conversion constraint from Foo into NotNull!(Foo) which i described in my post above.
Apr 22 2012
I made several tests with NotNull yesterday and actually they all passed. In special cases i didn't get a compiler error but then a runtime error is better then nothing. :) But there is still my problem with this: void foo(NotNull!(Foo) n) { } void bar(Foo n) { } in my optinion it must exist a way that both NotNull!(Foo) nf = new Foo(); foo(nf); bar(nf); and furhtermore Foo f = new Foo(); foo(f); bar(f); compiles. We need some hack, implicit cast or compiler cast that cast or passes Foo to NotNull!(Foo). Any suggestions?
Apr 23 2012
On Mon, 23 Apr 2012 09:14:12 +0200, Namespace <rswhite4 googlemail.com> wrote:I made several tests with NotNull yesterday and actually they all passed. In special cases i didn't get a compiler error but then a runtime error is better then nothing. :) But there is still my problem with this: void foo(NotNull!(Foo) n) { } void bar(Foo n) { } in my optinion it must exist a way that both NotNull!(Foo) nf = new Foo(); foo(nf); bar(nf); and furhtermore Foo f = new Foo(); foo(f); bar(f); compiles. We need some hack, implicit cast or compiler cast that cast or passes Foo to NotNull!(Foo). Any suggestions?No. The whole point of NotNull is that it should enforce not being null. Allowing implicit casting from PossiblyNull to NotNull would break this.
Apr 23 2012
On 23.04.2012 12:06, Simen Kjaeraas wrote:On Mon, 23 Apr 2012 09:14:12 +0200, Namespace <rswhite4 googlemail.com> wrote:Just include obligatory run-time check when crossing null-NotNull boundaries. -- Dmitry OlshanskyI made several tests with NotNull yesterday and actually they all passed. In special cases i didn't get a compiler error but then a runtime error is better then nothing. :) But there is still my problem with this: void foo(NotNull!(Foo) n) { } void bar(Foo n) { } in my optinion it must exist a way that both NotNull!(Foo) nf = new Foo(); foo(nf); bar(nf); and furhtermore Foo f = new Foo(); foo(f); bar(f); compiles. We need some hack, implicit cast or compiler cast that cast or passes Foo to NotNull!(Foo). Any suggestions?No. The whole point of NotNull is that it should enforce not being null. Allowing implicit casting from PossiblyNull to NotNull would break this.
Apr 23 2012
On Mon, 23 Apr 2012 10:38:27 +0200, Dmitry Olshansky <dmitry.olsh gmail.com> wrote:On 23.04.2012 12:06, Simen Kjaeraas wrote:Which carries with it hidden runtime costs that are unacceptable to some. The point of NotNull is twofold - safety (you know it's not null) and speed (you don't need to check if it's null). The latter goes out the window if implicit casting were allowed.On Mon, 23 Apr 2012 09:14:12 +0200, Namespace <rswhite4 googlemail.com> wrote:Just include obligatory run-time check when crossing null-NotNull boundaries.I made several tests with NotNull yesterday and actually they all passed. In special cases i didn't get a compiler error but then a runtime error is better then nothing. :) But there is still my problem with this: void foo(NotNull!(Foo) n) { } void bar(Foo n) { } in my optinion it must exist a way that both NotNull!(Foo) nf = new Foo(); foo(nf); bar(nf); and furhtermore Foo f = new Foo(); foo(f); bar(f); compiles. We need some hack, implicit cast or compiler cast that cast or passes Foo to NotNull!(Foo). Any suggestions?No. The whole point of NotNull is that it should enforce not being null. Allowing implicit casting from PossiblyNull to NotNull would break this.
Apr 23 2012
On Monday, 23 April 2012 at 08:47:22 UTC, Simen Kjaeraas wrote:On Mon, 23 Apr 2012 10:38:27 +0200, Dmitry Olshansky <dmitry.olsh gmail.com> wrote:Allow both: a type for explicit not null which cannot be changed to null and a keyword or some other construct which can check any possible object at compile time if it's null.On 23.04.2012 12:06, Simen Kjaeraas wrote:Which carries with it hidden runtime costs that are unacceptable to some. The point of NotNull is twofold - safety (you know it's not null) and speed (you don't need to check if it's null). The latter goes out the window if implicit casting were allowed.On Mon, 23 Apr 2012 09:14:12 +0200, Namespace <rswhite4 googlemail.com> wrote:Just include obligatory run-time check when crossing null-NotNull boundaries.I made several tests with NotNull yesterday and actually they all passed. In special cases i didn't get a compiler error but then a runtime error is better then nothing. :) But there is still my problem with this: void foo(NotNull!(Foo) n) { } void bar(Foo n) { } in my optinion it must exist a way that both NotNull!(Foo) nf = new Foo(); foo(nf); bar(nf); and furhtermore Foo f = new Foo(); foo(f); bar(f); compiles. We need some hack, implicit cast or compiler cast that cast or passes Foo to NotNull!(Foo). Any suggestions?No. The whole point of NotNull is that it should enforce not being null. Allowing implicit casting from PossiblyNull to NotNull would break this.
Apr 23 2012
No. The whole point of NotNull is that it should enforce not being null. Allowing implicit casting from PossiblyNull to NotNull would break this.Then i'm further for a keyword that checks an object for not null. Or you check at runtime to avoid null, e.g. with assert or enforce.
Apr 23 2012
Am 23.04.2012 09:14, schrieb Namespace:I made several tests with NotNull yesterday and actually they all passed. In special cases i didn't get a compiler error but then a runtime error is better then nothing. :) But there is still my problem with this: void foo(NotNull!(Foo) n) { } void bar(Foo n) { } in my optinion it must exist a way that both NotNull!(Foo) nf = new Foo(); foo(nf); bar(nf); and furhtermore Foo f = new Foo(); foo(f); bar(f); compiles. We need some hack, implicit cast or compiler cast that cast or passes Foo to NotNull!(Foo). Any suggestions?If you replace alias _notNullData this; with property T _notNullDataHelper() { assert(_notNullData !is null); return _notNullData; } alias _notNullDataHelper this; It will not be possible to assign to _notNullData It will still be possbile to use from other modules NotNull!T will implicitly convert to T (your first case) However T will not implicitly convert to NotNull!T (as far as I know such a implict conversion is not possible in D, i suggested a implicit modifier for a constructor to allow such implicit type conversions, but it was rejected) Kind Regards Benjamin Thaut
Apr 23 2012
On Monday, 23 April 2012 at 11:04:24 UTC, Benjamin Thaut wrote:Am 23.04.2012 09:14, schrieb Namespace:Yes, that's what i wrote a site before. Otherwise you couldn't use it in other modules, that's right.I made several tests with NotNull yesterday and actually they all passed. In special cases i didn't get a compiler error but then a runtime error is better then nothing. :) But there is still my problem with this: void foo(NotNull!(Foo) n) { } void bar(Foo n) { } in my optinion it must exist a way that both NotNull!(Foo) nf = new Foo(); foo(nf); bar(nf); and furhtermore Foo f = new Foo(); foo(f); bar(f); compiles. We need some hack, implicit cast or compiler cast that cast or passes Foo to NotNull!(Foo). Any suggestions?If you replace alias _notNullData this; with property T _notNullDataHelper() { assert(_notNullData !is null); return _notNullData; } alias _notNullDataHelper this; It will not be possible to assign to _notNullData It will still be possbile to use from other modulesNotNull!T will implicitly convert to T (your first case) However T will not implicitly convert to NotNull!T (as far as I know such a implict conversion is not possible in D, i suggested a implicit modifier for a constructor to allow such implicit type conversions, but it was rejected) Kind Regards Benjamin ThautThat is bad. Without the possibility of such implicit constructs NotNull isn't usefull at all. I wouldn't write for all the objects which i would check "method_with_not_null_object(ConvertToNotNull(f_obj));" That isn't helpfull, that makes more work as a sugesstion in the method with assert(obj !is null); and that was what i wanted avoid. Why this reluctance against a keyword to check a normal Object which is passed as parameter, e.g. notNull Foo f? I didn't understood it. Please explain that to me. My previous language was C++ and so my first thoughts were that only pointer types can be null but not references. And then i've learned that D allows this behavoiur for both: refernces e.g. objects that passes as parameter and even for pointer types. That's a point which i will never understand.
Apr 23 2012
On Monday, 23 April 2012 at 14:31:05 UTC, Namespace wrote:Yes, that's what i wrote a site before. Otherwise you couldn't use it in other modules, that's right.yeah i'll fix that next time i work on it.I wouldn't write for all the objects which i would check "method_with_not_null_object(ConvertToNotNull(f_obj));"The idea is to use NotNull!T to store your stuff, so there's no need to convert.Why this reluctance against a keyword to check a normal Object which is passed as parameter, e.g. notNull Foo f?Because the hardware already does that, for the most part. That's what "access violation" means. The hard part is figuring out /why/ it is null, and the not null type helps that by catching it when you store it instead of when you use it.
Apr 23 2012
On Monday, 23 April 2012 at 14:50:14 UTC, Adam D. Ruppe wrote:On Monday, 23 April 2012 at 14:31:05 UTC, Namespace wrote:So if i wouldn't want such annoying debugging for a simple error (which gave me no further information), i must catch this stupid access violation by myself with assert/enforce or i use for all relevant objects NotNull? That is very inconvenient... And all that because NullPointer Exceptions or checks to assume not null (even with a explicit keyword!) would decrease the speed?Yes, that's what i wrote a site before. Otherwise you couldn't use it in other modules, that's right.yeah i'll fix that next time i work on it.I wouldn't write for all the objects which i would check "method_with_not_null_object(ConvertToNotNull(f_obj));"The idea is to use NotNull!T to store your stuff, so there's no need to convert.Why this reluctance against a keyword to check a normal Object which is passed as parameter, e.g. notNull Foo f?Because the hardware already does that, for the most part. That's what "access violation" means. The hard part is figuring out /why/ it is null, and the not null type helps that by catching it when you store it instead of when you use it.
Apr 23 2012
I thought that something like this // not_null_struct.d NotNull!(T) assumeNotNull(T : Object)(T t) { return NotNull!(T)(t); } property NotNull!(T) makeNotNull(T : Object)() { T t = new T(); return assumeNotNull(t); } // not_null.d which import not_null_struct.d NotNull!(Foo) _convert() { //return NotNull!(Foo)(this); // prints: Stack overflow return assumeNotNull(this); } alias _convert this; would allow me to convert Foo to NotNull!(Foo) implicit. But it doesn't work. I get this error: not_null.d(37): Error: template instance not_null_struct.assumeNotNull!(Foo) recursive expansion Line 37 is the return in the _convert method. Does anybody know why? I thought that would a smart idea...
Apr 23 2012
On Monday, 23 April 2012 at 17:18:30 UTC, Namespace wrote:I thought that something like this // not_null_struct.d NotNull!(T) assumeNotNull(T : Object)(T t) { return NotNull!(T)(t); } property NotNull!(T) makeNotNull(T : Object)() { T t = new T(); return assumeNotNull(t); } // not_null.d which import not_null_struct.d NotNull!(Foo) _convert() { //return NotNull!(Foo)(this); // prints: Stack overflow return assumeNotNull(this); } alias _convert this; would allow me to convert Foo to NotNull!(Foo) implicit. But it doesn't work. I get this error: not_null.d(37): Error: template instance not_null_struct.assumeNotNull!(Foo) recursive expansion Line 37 is the return in the _convert method. Does anybody know why? I thought that would a smart idea...I see, if i comment out "alias _get this;" in NotNull it works fine and i can implicit convert Foo to NotNull!(Foo). But why doesn't it work shareable? In that case it would be nearly perfect for me. Does anyone know how it could work? In my opinion both variants have to work shareable. Don't they?
Apr 23 2012
After i'm sure, that this is a bug: Great work again. If this bug will be fixed soon or someone can help me to find a workaround, then NotNull would be exactly what I always wanted.
Apr 24 2012
On Sunday, 22 April 2012 at 10:58:10 UTC, Namespace wrote:If i got you right on git, you wouldn't allow something like this: NotNull!(Foo) f = new Foo(); and instead you want that everybody writes NotNull!(Foo) f = assumeNotNull(new Foo); Is that correct?No, I think that's too annoying, though I also think it is more correct. But my plan is to allow NotNull!Foo f = new Foo(). (This is a constructor, so removing opAssign doesn't change this.)there because of the explicit conversion constraint from Foo into NotNull!(Foo) which i described in my post above.That explicit conversion is one of the features of the type - it means the compiler will remind you when you missed something. There's really little benefit to checking at a function automatically. If you need that, you can always assert for it in an in{} contract. Or just use it and let the debugger take care of the rest. I think a debug build on Windows even gives a stack trace on null deref, but I'm not sure. The big benefit with not null types is making sure you don't store a null somewhere, since that's a lot harder to track down.
Apr 23 2012
On Saturday, 21 April 2012 at 23:18:40 UTC, Namespace wrote:I see you're right. Great! But it is only on git hub and not in the standard typecons header in 2.059, right?Right, I missed the deadline for that.
Apr 21 2012
Adam D. Ruppe:We can do not null in the library reasonably well. I have a basic one in github: https://github.com/D-Programming-Language/phobos/pull/477It says:I haven't actually used any NotNull in practice, but from the attached tests, it looks like it will work well - hence, the pull request.<I think before putting something in Phobos it's generally better to have used it in Real Code for some time. I am not sure a mostly-library-defined solution (mostly because disable is a built-in) is good enough compared to a solution built in the type system. I will try to use your NotNull struct. Bye, bearophile
Apr 21 2012
On Saturday, 21 April 2012 at 23:26:04 UTC, bearophile wrote:I think before putting something in Phobos it's generally better to have used it in Real Code for some time.I agree, but this comes up a LOT on the newsgroup, so I figure we need to get something up there to point people to.I am not sure a mostly-library-defined solution (mostly because disable is a built-in)lol, all library implementations use language features!I will try to use your NotNull struct.Thanks! Let you know what you think of it. I'm sure we can do a good job with this.
Apr 21 2012
On Saturday, 21 April 2012 at 22:18:02 UTC, Adam D. Ruppe wrote:We can do not null in the library reasonably well. I have a basic one in github: https://github.com/D-Programming-Language/phobos/pull/477I'm thinking those interested in not null will want something similar to the maybe type. As such checkNotNull shoud be more than throwing an exception. I have tried this, but it should get some constraints. Also wouldn't the new lambda syntax look nice with null here: null => unsafe(a)? import std.stdio; void main() { int* a; int i = 5; checkNull!( t => safe(t), () { unsafe(a); }) (a); a = &i; checkNull!( t => safe(t)) (a); } void checkNull(alias nn, alias n = () {}, T)(T a) { if(a !is null) nn(assumeNotNull(a)); else n(); } void safe(NotNull!(int*) i) { writeln(*i); } void unsafe(int* i) { writeln(i); }
Apr 22 2012
On Sunday, 22 April 2012 at 16:59:05 UTC, Jesse Phillips wrote:As such checkNotNull shoud be more than throwing an exception. I have tried this, but it should get some constraints. Also wouldn't the new lambda syntax look nice with null here: null => unsafe(a)?Yeah, I like this idea, though a lot of what I do is more like if(x !is null) use(x); hmmmm, the default could be to simply do nothing on the other side. I think we can work with the lambda idea. The other null related things on my mind are: 1) if we could make new return NotNull!T. I guess we could offer an alternative: NotNull!T create(T, Args...)(Args) { return assumeNotNull(new T(Args)); } Though "new" is so well entrenched that I don't think it is going anywhere, and having a language construct depend on a library structure is pretty meh. So meh. 2) When doing chained calls, have it simply ignore the rest when it hits null. suppose: if(a) if(auto b = a.something) b.more(); I guess some languages would call that a?.something?.more(); but I wonder if we can do it in a library somehow. ifNotNull(a).something.more(); Suppose it returns a wrapper of a that has an opDispatch or something that includes the if check, and wraps the rest of the return values. I'm pretty sure we can do that!
Apr 23 2012
On 04/21/2012 11:40 PM, Namespace wrote:My question is, why D hasn't got an explicit Keyword to check at compile time for non null references?It shouldn't be a special keyword. If the compiler can do the necessary analysis to actually enforce that the reference cannot hold a null reference, then it should be the default. Most references are not null.I understand that such check when they're implicit and refer to all objects they slow down the programm,How would such a check slow down the program? The rest of your post seems to indicate that you want a compile time check.but why doesn't exist an explicit keyword like ref or a simple ' ' before the Object name or value. Right now it's very annoying because i get a cryptical error message "Access violation" without any further informations and I have to debug. Only that way I can find where the Null references would access and then, why _and_ where the null references came from. That sucks. I hate it and so i write in every method to avoid null references "assert(obj !is null);". Now i get an assertion if obj is null and also the file and line. 50% less work then before. But it's still a runtime error and explicit work which can easily be checked by the compiler at compile time.'Easily' would be an oversimplification. There are distinct issues to be solved by the type system, mostly surrounding initialisation.Then i know: "oh there are null references and there shouldn't be any". So what are the reasons against a special keyword to let the compiler check for non references?There are seldom reasons _against_ a language feature. To make it in, there must be reasons to adapt it. And even more importantly, there must be a good design that integrates well with the rest of the language. Having a non-null type system would certainly be desirable, but it would be a breaking language change if it was actually designed to be useful.In what way would that be a regression?so why didn't D made it better and did implement something for that? Some variants I have already seen: const Foo obj, const Foo obj or my favourite: const ref Foo obj. GreetzWell, that is the grammar of the feature, but you have not described how it should work. (Saying that the compiler should emit an error for null references does not cut it.)
Apr 21 2012