digitalmars.D - (non)nullable types
- Brian (3/9) Feb 08 2009 i vote yes, i would absolutely love non-nullable types. in some cases i
- Nick Sabalausky (11/18) Feb 08 2009 Yes: You don't always need an object to be nullable, and in those cases,...
- Jason House (2/13) Feb 08 2009 Please, please give us non-nullable types! Use of a non-nullable refere...
- bearophile (4/6) Feb 09 2009 An explicit cast may be better/safer.
- Andrei Alexandrescu (4/9) Feb 09 2009 Non-nullable types are proper subtypes of nullable types. There is no
- bearophile (4/6) Feb 09 2009 Yes, sorry, often I misunderstood (I was thinking of the opposite situat...
- Alex Burton (15/15) Feb 09 2009 I vote yes.
- bearophile (4/5) Feb 09 2009 I suggest you to start a new thread (and to try to explain yourself a bi...
- Michel Fortin (18/29) Feb 09 2009 Same here.
- Christopher Wright (6/17) Feb 09 2009 This is called the Null Object Pattern. Often, you need a special
- Christopher Wright (8/19) Feb 09 2009 Oh, and I vote no. I think it's needless complexity. I code without any
- Sebastian Biallas (15/19) Feb 09 2009 That misses the point completely. It's not about you (as the programmer)...
- Nick Sabalausky (3/22) Feb 09 2009 Interesting, that is very nice, I like that idea a lot.
- Christopher Wright (9/23) Feb 11 2009 Your language features should get rid of bugs that are easy to make and
- Jarrett Billingsley (21/24) Feb 11 2009 Except when someone passes a null reference into a large, complex data
- Christopher Wright (11/29) Feb 11 2009 Or add an invariant. You know which field is null when it shouldn't be,
- Jarrett Billingsley (4/14) Feb 11 2009 What is your response to the part of my post that was cut off? You
- Christopher Wright (17/34) Feb 11 2009 You'll eventually need to convert between nullable(T) and
- Jarrett Billingsley (21/36) Feb 11 2009 And how is that any different than how it is now? Currently you do
- Christopher Wright (13/16) Feb 12 2009 I see what you're saying, though I'm certain there is a large minority
- grauzone (3/5) Feb 12 2009 This would foil all my plans to ignore or actively circumvent the new
- Brian (4/7) Feb 13 2009 after a bit of thought i dont think theres much/any benefit of forcing a...
- Nick Sabalausky (15/22) Feb 13 2009 I don't see much of a point in not forcing a check. I can't think of a c...
- Christopher Wright (11/35) Feb 13 2009 The primary use case would be:
- Nick Sabalausky (12/49) Feb 13 2009 I still like this that someone else mentioned:
- Denis Koroskin (8/67) Feb 13 2009 Or use an existing syntax:
- Nick Sabalausky (11/34) Feb 13 2009 I could live with that, but I'd prefer my suggestion because it wouldn't...
- Nick Sabalausky (19/55) Feb 13 2009 Another thing to think about is delegates. Even if classes are non-null ...
- Jarrett Billingsley (4/21) Feb 13 2009 I was thinking nullability would be applicable to all reference types.
- Michel Fortin (9/12) Feb 13 2009 That's right with me, except for arrays for which there is bound
- Michel Fortin (21/44) Feb 13 2009 The problem with retyping the same variable is that it may gives
- Nick Sabalausky (53/87) Feb 14 2009 --------
- Denis Koroskin (24/120) Feb 14 2009 Foo? myObj = ...;
- Yigal Chripun (5/138) Feb 14 2009 can't this be done with:
- Denis Koroskin (2/156) Feb 14 2009 It solves the simplest examples, but not more complex ones, so it is not...
- Yigal Chripun (6/166) Feb 14 2009 In what way it's not generic enough?
- bearophile (4/6) Feb 14 2009 If you want to turn D into a more functional language, then that may be ...
- Nick Sabalausky (4/10) Feb 14 2009 D's already becoming more functional. Evidence: pure, immutable,
- Andrei Alexandrescu (3/15) Feb 14 2009 ...std.functional.
- Nick Sabalausky (3/18) Feb 14 2009 Sorry, I'm still in D1-land ;-)
- Yigal Chripun (11/26) Feb 14 2009 Besides, such a change will allow us to remove the ugly ?: operator and
- Nick Sabalausky (13/23) Feb 14 2009 I like the ?: operator :-). It's short. But I agree it might be worth
- Yigal Chripun (14/39) Feb 14 2009 well, IMO there are better syntax options for templates but I doubt it
- Nick Sabalausky (57/161) Feb 14 2009 I blame fatigue ;)
- Daniel Keep (12/36) Feb 13 2009 Both of these syntaxes are solving a problem that doesn't exist. This
- Jarrett Billingsley (14/22) Feb 13 2009 Having only nullable references with no non-null counterpart is like a
- Daniel Keep (11/24) Feb 13 2009 This is (expletive) ridiculous.
- Jarrett Billingsley (6/11) Feb 13 2009 Oh...kay. That was kind of uncalled for. I'm sorry I don't keep tabs
- Daniel Keep (26/26) Feb 15 2009 Sorry, Jarrett. You're right; it was uncalled for. I was having a bad
- Don (5/20) Feb 16 2009 I am in complete agreement with you on all these points. Nullable types
- Sergey Gromov (10/14) Feb 16 2009 Hmm, I think I've got your point. The nullable types should work
- Brian (2/3) Feb 17 2009 i second that. this would be wonderful.
- Christopher Wright (7/24) Feb 17 2009 One possible change: implicit casting with an assertion that the
- Nick Sabalausky (11/13) Feb 17 2009 I can tell right now I wouldn't like that. That would make it far too ea...
- Christopher Wright (3/17) Feb 17 2009 I think I favor this, actually. If you don't care, you can cast
- Christopher Wright (16/34) Feb 18 2009 One problem here is static constructors. They're supposed to run in
- Daniel Keep (25/45) Feb 18 2009 Mmm... non-nullable types would also be the only type in D that cannot
- Christopher Wright (21/71) Feb 18 2009 You could have the compiler use the default constructor to create an
- Michel Fortin (12/17) Feb 17 2009 I think it's a good idea: good enough to be useful, simple enough to be
- Jarrett Billingsley (5/16) Feb 17 2009 Actually each little debug check has a separate internal flag in the
- Nick Sabalausky (39/75) Feb 13 2009 The entire point of all of this is to make dereferencing null (and I mea...
- Christopher Wright (10/18) Feb 14 2009 You're right for that small example. Now let's say you have an object a
- Jarrett Billingsley (20/31) Feb 14 2009 ....that's the entire point of non-null references.
- Christopher Wright (5/19) Feb 14 2009 No. I'm saying this class has a complex code path if some things are not...
- Nick Sabalausky (6/29) Feb 14 2009 You would only need to check when you're going to derefernce or convert ...
- Christopher Wright (32/36) Feb 14 2009 Let's say I originally have this:
- Denis Koroskin (8/44) Feb 14 2009 private void doPart1()
- Christopher Wright (2/10) Feb 14 2009 Fuck no.
- Nick Sabalausky (17/45) Feb 14 2009 Because some other function or codepath could still accidentally be brea...
- Nick Sabalausky (4/9) Feb 14 2009 Sorry, that should be "...so you're right back to inviting hidden null
- Christopher Wright (18/36) Feb 15 2009 Yes, but I'm using nullable variables. I'm happy with getting a hardware...
- Nick Sabalausky (8/9) Feb 15 2009 Ok, now *that* I could live with (at least if we ever actually got the
- Michel Fortin (19/21) Feb 14 2009 I leaning to think it'd be best to have non-nullable pointers that just
- Christopher Wright (7/11) Feb 14 2009 I believe you should be able to use a nullable variable like its
- Christopher Wright (3/16) Feb 14 2009 I hate it.
- Nick Sabalausky (4/20) Feb 14 2009 You're right, I've come to realize that in a different branch of this
- Sebastian Biallas (3/6) Feb 11 2009 A runtime check is completely different from a compile time check.
- Sebastian Biallas (18/42) Feb 11 2009 Once your software is running, an easy to fix bug is just as bad as an
- Don (5/53) Feb 11 2009 Agreed. NPE are normally an easy to fix, easy to diagnose bug, but it
- Brian (7/9) Feb 11 2009 i couldnt agree more. i think this would be a great addition to D.
- grauzone (10/12) Feb 12 2009 I wouldn't mind if the compiler only inserted assert()s for me. Having
- Nick Sabalausky (15/27) Feb 12 2009 I've been wondering about that too, as I certainly see the value in
- Brian (7/18) Feb 09 2009 well, at the very least id like to see a (optional) warning/error for
- Brian (18/24) Feb 09 2009 just to clarify, this is what id like. given this code:
On Mon, 09 Feb 2009 04:25:55 +0300, Denis Koroskin wrote:So, let's ask the community: Would you like to see nullable types in D? http://www.micropoll.com/akira/mpview/539369-138652 (please, don't abuse by voting multiple time) Explain your reasoning in newsgroups. Thank you.i vote yes, i would absolutely love non-nullable types. in some cases i even use dummy objects to avoid null checks.
Feb 08 2009
On Mon, 09 Feb 2009 04:25:55 +0300, Denis Koroskin wrote:Yes: You don't always need an object to be nullable, and in those cases, having it nullable only serves to create a need for extra checking (Take a look at the ANTLR/StringBuilder Java source to see what happens when nullability goes too far. Disclaimer: I don't mean that as a jab at ANTLR/StringBuilder or the people behind it). However, I could be swayed to change my mind against it if it were shown that nullable/nonnullable could not be done without ending up with a bunch of compatibility/conversion/API problems. BTW, May I politely refer whoever used/made micropoll to the "OT: Scripting on websites [Was: Re: QtD 0.1 is out!]" sub-discussion over on digitalmars.D.announce? ;-)So, let's ask the community: Would you like to see nullable types in D? http://www.micropoll.com/akira/mpview/539369-138652 (please, don't abuse by voting multiple time) Explain your reasoning in newsgroups. Thank you.
Feb 08 2009
Brian wrote:On Mon, 09 Feb 2009 04:25:55 +0300, Denis Koroskin wrote:Please, please give us non-nullable types! Use of a non-nullable reference segfaults and this would at least allow safer code to be written. Non-nullable types should be implicitly castable to nullable types when making function calls that don't support them.So, let's ask the community: Would you like to see nullable types in D? http://www.micropoll.com/akira/mpview/539369-138652 (please, don't abuse by voting multiple time) Explain your reasoning in newsgroups. Thank you.i vote yes, i would absolutely love non-nullable types. in some cases i even use dummy objects to avoid null checks.
Feb 08 2009
Jason House:Non-nullable types should be implicitly castable to nullable types when making function calls that don't support them.An explicit cast may be better/safer. Bye, bearophile
Feb 09 2009
bearophile wrote:Jason House:Non-nullable types are proper subtypes of nullable types. There is no added safety in requiring a cast. AndreiNon-nullable types should be implicitly castable to nullable types when making function calls that don't support them.An explicit cast may be better/safer.
Feb 09 2009
Andrei Alexandrescu:Non-nullable types are proper subtypes of nullable types. There is no added safety in requiring a cast.Yes, sorry, often I misunderstood (I was thinking of the opposite situation). Bye, bearophile
Feb 09 2009
I vote yes. I was pretty sure the topic was refering to the ability to specify a pointer that could not be set to 0. I totally agree with this rule, and enforce it in all my C++ code with smart pointers. class X { }; X x; //in D or X * x; //in C++ Setting x to zero or any other value that is not the address of an instance of X is bad bad bad, and should be discouraged at all costs. If I ask for a pointer to an instance of X and you give me a zero or 0x0123456 or anything else, it is like mixing in a bicycle when a recipe asked for a cup of olive oil. This is a huge source of bugs where people best described as C programmers do C++. In D the mistake can be made especially when a struct changes into a class, and allocations are not changed. Like X x has to change to X x = new X (which is a bit repetitive in D IMHO). I think the default should be to have the native X x (D pointer to class) to be instantiating the class, and the X x = new Y should only be required when X and Y are different (inherited) types and X x(32); when the class X has a ctor with arguments ( actually why don't I start a new thread about this) There are many better ways to write code than using nullable pointers.
Feb 09 2009
Alex Burton:( actually why don't I start a new thread about this)I suggest you to start a new thread (and to try to explain yourself a bit better). Bye, bearophile
Feb 09 2009
On 2009-02-08 23:19:55 -0500, Brian <digitalmars brianguertin.com> said:On Mon, 09 Feb 2009 04:25:55 +0300, Denis Koroskin wrote:Same here. A non-nullable pointer, when used as a function argument, is a contract the compiler can enforce at the call site. If 80% of your functions accept only non-nullable pointers, then it means you can remove about 80% of your checks for null without worries of seeing your program crash. For global and member variables, non-nullable pointers means you can get an error exactly where the infringing code first put a null where there shouldn't be one; not later when someone tries to access it. And I think non-nullable should be the default because it's safer and it'd force people to be explicit when they want to take the responsability to work with nullable ones. So it's a yes. -- Michel Fortin michel.fortin michelf.com http://michelf.com/So, let's ask the community: Would you like to see nullable types in D? http://www.micropoll.com/akira/mpview/539369-138652 (please, don't abuse by voting multiple time) Explain your reasoning in newsgroups. Thank you.i vote yes, i would absolutely love non-nullable types. in some cases i even use dummy objects to avoid null checks.
Feb 09 2009
Brian wrote:On Mon, 09 Feb 2009 04:25:55 +0300, Denis Koroskin wrote:This is called the Null Object Pattern. Often, you need a special instance or subclass to satisfy the NOP. For instance, my company's staff scheduling program might get a null EmployeeGroup class that would need a reference to the Customer object, unlike other EmployeeGroups, in order to claim that it contains all employees.So, let's ask the community: Would you like to see nullable types in D? http://www.micropoll.com/akira/mpview/539369-138652 (please, don't abuse by voting multiple time) Explain your reasoning in newsgroups. Thank you.i vote yes, i would absolutely love non-nullable types. in some cases i even use dummy objects to avoid null checks.
Feb 09 2009
Brian wrote:On Mon, 09 Feb 2009 04:25:55 +0300, Denis Koroskin wrote:Oh, and I vote no. I think it's needless complexity. I code without any special care for null objects, and I get a segfault or NullReferenceException maybe once a week, probably less. I've always been able to track down the bug very quickly. Having types be non-nullable by default would harm my productivity a fair bit. Having them be optionally non-nullable would be okay, as long as the libraries I use don't use non-nullable types.So, let's ask the community: Would you like to see nullable types in D? http://www.micropoll.com/akira/mpview/539369-138652 (please, don't abuse by voting multiple time) Explain your reasoning in newsgroups. Thank you.i vote yes, i would absolutely love non-nullable types. in some cases i even use dummy objects to avoid null checks.
Feb 09 2009
Christopher Wright wrote:Oh, and I vote no. I think it's needless complexity. I code without any special care for null objects, and I get a segfault or NullReferenceException maybe once a week, probably less. I've always been able to track down the bug very quickly.That misses the point completely. It's not about you (as the programmer) getting NPEs; it's about the user getting bug-free software in the first place. In most cases a segfault/NPE is easy to track down for the programmer, I guess nobody would object to this. But once the software is shipped, it's a very serious problem: It's a situation the programmer didn't thought about so you usually have a data loss. I really like the approach of the Nice[1] language: Before you can access a nullable type you have to test whether it's null. After the test, the type is automagically converted to a nonnullable type. This language doesn't have a NPE, so you *know* that your software is bug-free in this regard. [1] http://nice.sf.net Sebastian
Feb 09 2009
"Sebastian Biallas" <groups.5.sepp spamgourmet.com> wrote in message news:gmpsun$14dj$1 digitalmars.com...Christopher Wright wrote:Interesting, that is very nice, I like that idea a lot.Oh, and I vote no. I think it's needless complexity. I code without any special care for null objects, and I get a segfault or NullReferenceException maybe once a week, probably less. I've always been able to track down the bug very quickly.That misses the point completely. It's not about you (as the programmer) getting NPEs; it's about the user getting bug-free software in the first place. In most cases a segfault/NPE is easy to track down for the programmer, I guess nobody would object to this. But once the software is shipped, it's a very serious problem: It's a situation the programmer didn't thought about so you usually have a data loss. I really like the approach of the Nice[1] language: Before you can access a nullable type you have to test whether it's null. After the test, the type is automagically converted to a nonnullable type. This language doesn't have a NPE, so you *know* that your software is bug-free in this regard. [1] http://nice.sf.net Sebastian
Feb 09 2009
Sebastian Biallas wrote:Christopher Wright wrote:Your language features should get rid of bugs that are easy to make and difficult to track down. It's not worthwhile to alter your language to remove easily found, easily fixed bugs. Logic errors are difficult to find. Your language cannot help you eliminate those (though contracts and unittests can help you find them). If you do not test your software extensively, you will ship software with logic errors. The testing required to find logic errors will also find low-level errors like segfaults.Oh, and I vote no. I think it's needless complexity. I code without any special care for null objects, and I get a segfault or NullReferenceException maybe once a week, probably less. I've always been able to track down the bug very quickly.That misses the point completely. It's not about you (as the programmer) getting NPEs; it's about the user getting bug-free software in the first place. In most cases a segfault/NPE is easy to track down for the programmer, I guess nobody would object to this. But once the software is shipped, it's a very serious problem: It's a situation the programmer didn't thought about so you usually have a data loss.
Feb 11 2009
On Wed, Feb 11, 2009 at 3:40 PM, Christopher Wright <dhasenan gmail.com> wrote:Your language features should get rid of bugs that are easy to make and difficult to track down. It's not worthwhile to alter your language to remove easily found, easily fixed bugs.Except when someone passes a null reference into a large, complex data structure and that reference is passed around blindly and never dereferenced until somewhere far down the line, giving you a segfault in a program location that you never would have expected. By then it's much more difficult to figure out where that null reference came from. I've had a much larger share of these kinds of null reference errors than the "oops someone passed a null into my function and I didn't account for it" kind. Disallowing null references on most public interface functions from the beginning would make those kinds of bugs nonexistent. Otherwise, you have to put explicit runtime null checks on every public interface function, and woe to the guy who forgets to do that. Not to mention you now have to write all these stupid unittests to throw nulls at the code to see if it barfs correctly, rather than it being a simple error caught by the compiler. This reeks of the development problems that dynamic languages have! We have static compilation for a reason; why not take advantage of it? Having null references be the default - nay, the only - option is a useless bit of C arcana that should be dropped. It's a dangerous use of in-band signaling on par with error return codes.
Feb 11 2009
Jarrett Billingsley wrote:On Wed, Feb 11, 2009 at 3:40 PM, Christopher Wright <dhasenan gmail.com> wrote:Or add an invariant. You know which field is null when it shouldn't be, so that should be simple enough. Or use a property rather than a field and add a contract. This covers the same cases that non-nullable types do, though admittedly with slightly less granularity. A complex datastructure might have a complex initialization process that is best spread across a few lines of code rather than happening all at once. If that is the case, you *can't* use non-nullable types, because that restriction isn't valid until the object is fully initialized. But you can still use contracts here.Your language features should get rid of bugs that are easy to make and difficult to track down. It's not worthwhile to alter your language to remove easily found, easily fixed bugs.Except when someone passes a null reference into a large, complex data structure and that reference is passed around blindly and never dereferenced until somewhere far down the line, giving you a segfault in a program location that you never would have expected. By then it's much more difficult to figure out where that null reference came from. I've had a much larger share of these kinds of null reference errors than the "oops someone passed a null into my function and I didn't account for it" kind. Disallowing null references on most public interface functions from the beginning would make those kinds of bugs nonexistent. Otherwise, you have to put explicit runtime null checks on every public interface function, and woe to the guy who forgets to do that.
Feb 11 2009
On Wed, Feb 11, 2009 at 5:23 PM, Christopher Wright <dhasenan gmail.com> wrote:Or add an invariant. You know which field is null when it shouldn't be, so that should be simple enough. Or use a property rather than a field and add a contract. This covers the same cases that non-nullable types do, though admittedly with slightly less granularity. A complex datastructure might have a complex initialization process that is best spread across a few lines of code rather than happening all at once. If that is the case, you *can't* use non-nullable types, because that restriction isn't valid until the object is fully initialized. But you can still use contracts here.What is your response to the part of my post that was cut off? You know, the part about having to write stupid contracts and how the compiler can and should be checking this kind of thing?
Feb 11 2009
Jarrett Billingsley wrote:On Wed, Feb 11, 2009 at 5:23 PM, Christopher Wright <dhasenan gmail.com> wrote:You'll eventually need to convert between nullable(T) and not_nullable(T). This requires runtime checks. A struct NotNull(T) could do the same, with some significant disadvantages. But making not_nullable the default, I'm not sure how much work that would add for me. I know it would add a fair bit for Walter. Having it as an option and not the default would probably make it sufficiently annoying that people would not use it, in which case it's no better than adding an invariant. On the one hand, not_nullable by default would probably do me no good. On the other, it would cost me little effort in most cases, most likely, unless I got sufficiently annoyed at all the little cases that I gave up and made every variable nullable by default. It would be cool if we could accompany these discussions with sample compilers that implement the feature in question. That way, I could speak with some certainty when I said that a proposed feature would be annoying.Or add an invariant. You know which field is null when it shouldn't be, so that should be simple enough. Or use a property rather than a field and add a contract. This covers the same cases that non-nullable types do, though admittedly with slightly less granularity. A complex datastructure might have a complex initialization process that is best spread across a few lines of code rather than happening all at once. If that is the case, you *can't* use non-nullable types, because that restriction isn't valid until the object is fully initialized. But you can still use contracts here.What is your response to the part of my post that was cut off? You know, the part about having to write stupid contracts and how the compiler can and should be checking this kind of thing?
Feb 11 2009
On Wed, Feb 11, 2009 at 8:05 PM, Christopher Wright <dhasenan gmail.com> wrote:You'll eventually need to convert between nullable(T) and not_nullable(T). This requires runtime checks. A struct NotNull(T) could do the same, with some significant disadvantages.And how is that any different than how it is now? Currently you do "if(blah is null) do one thing; else do something else;". This kind of pattern can actually be picked up by the compiler and it would say "hey, blah is null in the first clause but I know it's not null in the second." I think Andrei mentioned this as "flow-dependent typing"? Or something like that. The "if(auto blah = something) ... else ..." pattern also fits very nicely with nullable references.But making not_nullable the default, I'm not sure how much work that would add for me. I know it would add a fair bit for Walter. Having it as an option and not the default would probably make it sufficiently annoying that people would not use it, in which case it's no better than adding an invariant.If anything, most of your code would probably just go on working as it has. The few cases where you actually allow null, you'd have to annotate the type, and the compiler would be able to do flow-dependent typing in a vast majority of the cases. In the other cases, where you don't expect null (and forgot to check for it), the compiler will happily point out when you're a moron and pass null to a non-null parameter.On the one hand, not_nullable by default would probably do me no good. On the other, it would cost me little effort in most cases, most likely, unless I got sufficiently annoyed at all the little cases that I gave up and made every variable nullable by default.Except honestly, the number of cases where you _don't_ want something to be null far outweighs the number of cases where you _do_. It's not exactly as insidious as the "throws" clause.It would be cool if we could accompany these discussions with sample compilers that implement the feature in question. That way, I could speak with some certainty when I said that a proposed feature would be annoying.It would, wouldn't it! That would be nice if we had a nice compiler that we could modify and compile into an EXE. Like DMD. FFS.
Feb 11 2009
Jarrett Billingsley wrote:Except honestly, the number of cases where you _don't_ want something to be null far outweighs the number of cases where you _do_. It's not exactly as insidious as the "throws" clause.I see what you're saying, though I'm certain there is a large minority of cases in which I do want to allow nulls. I really want to see how painful it would be to have non-nullable types by default. There's also the matter of, can I use a nullable variable like a normal variable? For example: nullable Foo foo = something; foo.doStuff(); Brian mentioned having to check if the variable is null before using it. This would not be easy to implement, and it might be a bit hard to use. Again, I'd have to see it in use. While we're talking about hacking the compiler, how about const by default? :P
Feb 12 2009
While we're talking about hacking the compiler, how about const by default? :PThis would foil all my plans to ignore or actively circumvent the new const features. It's already very annoying to cast the string literals to the good old char[].
Feb 12 2009
On Thu, 12 Feb 2009 08:41:54 -0500, Christopher Wright wrote:Brian mentioned having to check if the variable is null before using it. This would not be easy to implement, and it might be a bit hard to use. Again, I'd have to see it in use.after a bit of thought i dont think theres much/any benefit of forcing a check. if nonnullable was the default then using a nullable version is expected to be unusual and potentially unsafe.
Feb 13 2009
"Brian" <digitalmars brianguertin.com> wrote in message news:gn3dfn$2lp3$1 digitalmars.com...On Thu, 12 Feb 2009 08:41:54 -0500, Christopher Wright wrote:I don't see much of a point in not forcing a check. I can't think of a case where it would be useful or desirable to use a nullable type without first checking for null (except for passing it to a func that takes a nullable as a param or assigning it to another nullable of the same type, but presumably the check wouldn't be required in those cases). So it may as well be forced (when dereferencing and converting to non-nullable), since you'd never really want/need to do otherwise. Even if the compiler simplified the process by only accepting the exact pattern of "if(x !is null)...", and didn't do any fancier analysis than that, I would still consider that accptable since, as you said, it would be a non-standard use. So therefore, a (very) minor inconvenience like that would be acceptable, particularly considering it would essentially guarantee no null reference errors (aside from manual use of pointers, of course).Brian mentioned having to check if the variable is null before using it. This would not be easy to implement, and it might be a bit hard to use. Again, I'd have to see it in use.after a bit of thought i dont think theres much/any benefit of forcing a check. if nonnullable was the default then using a nullable version is expected to be unusual and potentially unsafe.
Feb 13 2009
Nick Sabalausky wrote:"Brian" <digitalmars brianguertin.com> wrote in message news:gn3dfn$2lp3$1 digitalmars.com...The primary use case would be: nullable T y = something; non_nullable T x; if (y) x = non_nullable_cast(y); else return; This is a problem if T cannot be allocated by default. I have to do something like: nullable T y = something; if (!y) return; auto x = non_nullable_cast(y); That isn't so bad.On Thu, 12 Feb 2009 08:41:54 -0500, Christopher Wright wrote:I don't see much of a point in not forcing a check. I can't think of a case where it would be useful or desirable to use a nullable type without first checking for null (except for passing it to a func that takes a nullable as a param or assigning it to another nullable of the same type, but presumably the check wouldn't be required in those cases). So it may as well be forced (when dereferencing and converting to non-nullable), since you'd never really want/need to do otherwise. Even if the compiler simplified the process by only accepting the exact pattern of "if(x !is null)...", and didn't do any fancier analysis than that, I would still consider that accptable since, as you said, it would be a non-standard use. So therefore, a (very) minor inconvenience like that would be acceptable, particularly considering it would essentially guarantee no null reference errors (aside from manual use of pointers, of course).Brian mentioned having to check if the variable is null before using it. This would not be easy to implement, and it might be a bit hard to use. Again, I'd have to see it in use.after a bit of thought i dont think theres much/any benefit of forcing a check. if nonnullable was the default then using a nullable version is expected to be unusual and potentially unsafe.
Feb 13 2009
"Christopher Wright" <dhasenan gmail.com> wrote in message news:gn3os2$f6j$3 digitalmars.com...Nick Sabalausky wrote:I still like this that someone else mentioned: T? x = something; if(x !is null) { // x is implicitly "T" here, not "T?" } else { // handle null condition (x is still "T?") }"Brian" <digitalmars brianguertin.com> wrote in message news:gn3dfn$2lp3$1 digitalmars.com...The primary use case would be: nullable T y = something; non_nullable T x; if (y) x = non_nullable_cast(y); else return; This is a problem if T cannot be allocated by default. I have to do something like: nullable T y = something; if (!y) return; auto x = non_nullable_cast(y); That isn't so bad.On Thu, 12 Feb 2009 08:41:54 -0500, Christopher Wright wrote:I don't see much of a point in not forcing a check. I can't think of a case where it would be useful or desirable to use a nullable type without first checking for null (except for passing it to a func that takes a nullable as a param or assigning it to another nullable of the same type, but presumably the check wouldn't be required in those cases). So it may as well be forced (when dereferencing and converting to non-nullable), since you'd never really want/need to do otherwise. Even if the compiler simplified the process by only accepting the exact pattern of "if(x !is null)...", and didn't do any fancier analysis than that, I would still consider that accptable since, as you said, it would be a non-standard use. So therefore, a (very) minor inconvenience like that would be acceptable, particularly considering it would essentially guarantee no null reference errors (aside from manual use of pointers, of course).Brian mentioned having to check if the variable is null before using it. This would not be easy to implement, and it might be a bit hard to use. Again, I'd have to see it in use.after a bit of thought i dont think theres much/any benefit of forcing a check. if nonnullable was the default then using a nullable version is expected to be unusual and potentially unsafe.
Feb 13 2009
On Fri, 13 Feb 2009 21:43:22 +0300, Nick Sabalausky <a a.a> wrote:"Christopher Wright" <dhasenan gmail.com> wrote in message news:gn3os2$f6j$3 digitalmars.com...Or use an existing syntax: Foo? foo = ...; if (Foo value = foo) { // value is a local variable that is only accessible if foo is not null } else { // value is not accessible here }Nick Sabalausky wrote:I still like this that someone else mentioned: T? x = something; if(x !is null) { // x is implicitly "T" here, not "T?" } else { // handle null condition (x is still "T?") }"Brian" <digitalmars brianguertin.com> wrote in message news:gn3dfn$2lp3$1 digitalmars.com...The primary use case would be: nullable T y = something; non_nullable T x; if (y) x = non_nullable_cast(y); else return; This is a problem if T cannot be allocated by default. I have to do something like: nullable T y = something; if (!y) return; auto x = non_nullable_cast(y); That isn't so bad.On Thu, 12 Feb 2009 08:41:54 -0500, Christopher Wright wrote:I don't see much of a point in not forcing a check. I can't think of a case where it would be useful or desirable to use a nullable type without first checking for null (except for passing it to a func that takes a nullable as a param or assigning it to another nullable of the same type, but presumably the check wouldn't be required in those cases). So it may as well be forced (when dereferencing and converting to non-nullable), since you'd never really want/need to do otherwise. Even if the compiler simplified the process by only accepting the exact pattern of "if(x !is null)...", and didn't do any fancier analysis than that, I would still consider that accptable since, as you said, it would be a non-standard use. So therefore, a (very) minor inconvenience like that would be acceptable, particularly considering it would essentially guarantee no null reference errors (aside from manual use of pointers, of course).Brian mentioned having to check if the variable is null before using it. This would not be easy to implement, and it might be a bit hard to use. Again, I'd have to see it in use.after a bit of thought i dont think theres much/any benefit of forcing a check. if nonnullable was the default then using a nullable version is expected to be unusual and potentially unsafe.
Feb 13 2009
"Denis Koroskin" <2korden gmail.com> wrote in message news:op.upazx0d4o7cclz proton.creatstudio.intranet...On Fri, 13 Feb 2009 21:43:22 +0300, Nick Sabalausky <a a.a> wrote:I could live with that, but I'd prefer my suggestion because it wouldn't require the creation of an extra label for what's essentially the same variable. With your code we'd just end up with a whole bunch of: Foo? myObj = ...; if (Foo nonnullMyObj = myObj) //etc... // or Foo? nullableMyObj = ...; if (Foo myObj = nullableMyObj) //etc... ...Which just seems unnecessary to me.I still like this that someone else mentioned: T? x = something; if(x !is null) { // x is implicitly "T" here, not "T?" } else { // handle null condition (x is still "T?") }Or use an existing syntax: Foo? foo = ...; if (Foo value = foo) { // value is a local variable that is only accessible if foo is not null } else { // value is not accessible here }
Feb 13 2009
"Nick Sabalausky" <a a.a> wrote in message news:gn4g2n$fbf$1 digitalmars.com..."Denis Koroskin" <2korden gmail.com> wrote in message news:op.upazx0d4o7cclz proton.creatstudio.intranet...Another thing to think about is delegates. Even if classes are non-null by default, we can still get the same old null reference problem with delegates: class Foo { void delegate() dg; void callDg() { dg(); // Oops! Forgot to check for null!! } } void main() { auto f = new Foo(); f.callDg(); } This could probably be solved by whatever mechanism is used for classes.On Fri, 13 Feb 2009 21:43:22 +0300, Nick Sabalausky <a a.a> wrote:I could live with that, but I'd prefer my suggestion because it wouldn't require the creation of an extra label for what's essentially the same variable. With your code we'd just end up with a whole bunch of: Foo? myObj = ...; if (Foo nonnullMyObj = myObj) //etc... // or Foo? nullableMyObj = ...; if (Foo myObj = nullableMyObj) //etc... ...Which just seems unnecessary to me.I still like this that someone else mentioned: T? x = something; if(x !is null) { // x is implicitly "T" here, not "T?" } else { // handle null condition (x is still "T?") }Or use an existing syntax: Foo? foo = ...; if (Foo value = foo) { // value is a local variable that is only accessible if foo is not null } else { // value is not accessible here }
Feb 13 2009
On Fri, Feb 13, 2009 at 3:23 PM, Nick Sabalausky <a a.a> wrote:Another thing to think about is delegates. Even if classes are non-null by default, we can still get the same old null reference problem with delegates: class Foo { void delegate() dg; void callDg() { dg(); // Oops! Forgot to check for null!! } } void main() { auto f = new Foo(); f.callDg(); } This could probably be solved by whatever mechanism is used for classes.I was thinking nullability would be applicable to all reference types. A null pointer, delegate, array, or whatever is just as bad as a null reference.
Feb 13 2009
On 2009-02-13 16:30:59 -0500, Jarrett Billingsley <jarrett.billingsley gmail.com> said:I was thinking nullability would be applicable to all reference types. A null pointer, delegate, array, or whatever is just as bad as a null reference.That's right with me, except for arrays for which there is bound checking safeties in place. A null array and an empty array should be undistinguishable in my opinion. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Feb 13 2009
On 2009-02-13 14:01:57 -0500, "Nick Sabalausky" <a a.a> said:The problem with retyping the same variable is that it may gives strange situations. For instance, is this an error? Foo? myObj = ...; if (myObj !is null) { doSomethingWith(myObj); myObj = null; // should this be an error? } And what about: Foo? myObj = ...; while (myObj !is null) myObj = myObj.next; If you want to avoid verbosity, you'll need to retype the variable until it gets assigned another potentially non-null value. Basically, you'll need to perform flow analysis inside the function to enforce that. -- Michel Fortin michel.fortin michelf.com http://michelf.com/Or use an existing syntax: Foo? foo = ...; if (Foo value = foo) { // value is a local variable that is only accessible if foo is not null } else { // value is not accessible here }I could live with that, but I'd prefer my suggestion because it wouldn't require the creation of an extra label for what's essentially the same variable. With your code we'd just end up with a whole bunch of: Foo? myObj = ...; if (Foo nonnullMyObj = myObj) //etc... // or Foo? nullableMyObj = ...; if (Foo myObj = nullableMyObj) //etc... ...Which just seems unnecessary to me.
Feb 13 2009
"Michel Fortin" <michel.fortin michelf.com> wrote in message news:gn4pl9$1217$1 digitalmars.com...On 2009-02-13 14:01:57 -0500, "Nick Sabalausky" <a a.a> said:-------- // This (a more generalized case of above)... Foo? myObj = ...; if(myObj !is null) { bar1(myObj); if(blah1 > blah2) myObj = null; // Yes, error bar2(); } // ...would change to this... Foo? myObj = ...; bool turnToNull=false; if(myObj !is null) { bar1(myObj); if(blah1 > blah2) turnToNull = true; } if(turnToNull) { myObj = null; bar2(); } --------Foo? myObj = ...; if (myObj !is null) { doSomethingWith(myObj); myObj = null; // should this be an error? }Or use an existing syntax: Foo? foo = ...; if (Foo value = foo) { // value is a local variable that is only accessible if foo is not null } else { // value is not accessible here }I could live with that, but I'd prefer my suggestion because it wouldn't require the creation of an extra label for what's essentially the same variable. With your code we'd just end up with a whole bunch of: Foo? myObj = ...; if (Foo nonnullMyObj = myObj) //etc... // or Foo? nullableMyObj = ...; if (Foo myObj = nullableMyObj) //etc... ...Which just seems unnecessary to me.And what about: Foo? myObj = ...; while (myObj !is null) myObj = myObj.next;-------- Foo? myObj = ...; while(true) { if(myObj.next !is null) myObj = myObj.next; else break; } myObj = null; //this line optional // Or, if you don't like "while(true)", // you could use a "bool done" flag. -------- With Denis's syntax, I'm not sure how the second one would be possible, but the first one would certainly be nicer. So I'm tempted to say that both syntaxes should be allowed... However, you do have a valid point that my syntax has a problem whenever assigning a possibly-null value to the original nullable variable from within the scope of the null-check. It can definitely be worked around, but I am coming to realize that maybe removing a variable's nullability shouldn't happen implicitly unless it can also be added back implicity - which would require flow analysis. Between that and the difficultly of Denis's syntax handling that simple while loop example, I guess full-blown flow-analysis would be needed after all in order to realistically eliminate null reference errors on nullable types. Dang!
Feb 14 2009
On Sat, 14 Feb 2009 11:39:17 +0300, Nick Sabalausky <a a.a> wrote:"Michel Fortin" <michel.fortin michelf.com> wrote in message news:gn4pl9$1217$1 digitalmars.com...Dang! NullPointerException, because you never checked myObj against nullOn 2009-02-13 14:01:57 -0500, "Nick Sabalausky" <a a.a> said:-------- // This (a more generalized case of above)... Foo? myObj = ...; if(myObj !is null) { bar1(myObj); if(blah1 > blah2) myObj = null; // Yes, error bar2(); } // ...would change to this... Foo? myObj = ...; bool turnToNull=false; if(myObj !is null) { bar1(myObj); if(blah1 > blah2) turnToNull = true; } if(turnToNull) { myObj = null; bar2(); } --------Foo? myObj = ...; if (myObj !is null) { doSomethingWith(myObj); myObj = null; // should this be an error? }Or use an existing syntax: Foo? foo = ...; if (Foo value = foo) { // value is a local variable that is only accessible if foo is not null } else { // value is not accessible here }I could live with that, but I'd prefer my suggestion because it wouldn't require the creation of an extra label for what's essentially the same variable. With your code we'd just end up with a whole bunch of: Foo? myObj = ...; if (Foo nonnullMyObj = myObj) //etc... // or Foo? nullableMyObj = ...; if (Foo myObj = nullableMyObj) //etc... ...Which just seems unnecessary to me.And what about: Foo? myObj = ...; while (myObj !is null) myObj = myObj.next;-------- Foo? myObj = ...; while(true) { if(myObj.next !is null)myObj = myObj.next; else break; } myObj = null; //this line optional // Or, if you don't like "while(true)", // you could use a "bool done" flag. -------- With Denis's syntax, I'm not sure how the second one would be possible,Foo? myObj = ...; if (Foo obj = myObj) { while (true) { if (auto next = obj.next) { obj = next; } else { break; } } }but the first one would certainly be nicer. So I'm tempted to say that both syntaxes should be allowed... However, you do have a valid point that my syntax has a problem whenever assigning a possibly-null value to the original nullable variable from within the scope of the null-check. It can definitely be worked around, but I am coming to realize that maybe removing a variable's nullability shouldn't happen implicitly unless it can also be added back implicity - which would require flow analysis. Between that and the difficultly of Denis's syntax handling that simple while loop example, I guess full-blown flow-analysis would be needed after all in order to realistically eliminate null reference errors on nullable types. Dang!I don't think code flow analysis the way you suggest is useful. I certainly don't want my variable types to be changed at some point after null-check. Code flow analysis would be nice to have, but in a different way: Foo b; // not initialized, can not be read yet if (condition) { b = createFoo(42); } else if (otherCondition) { b = new Foo(); } else { // return b; // error, b is write only return; } // b is both read/write accessible at this point
Feb 14 2009
Denis Koroskin wrote:On Sat, 14 Feb 2009 11:39:17 +0300, Nick Sabalausky <a a.a> wrote:can't this be done with: Foo b = condition ? createFoo(42) : (otherCondition ? new Foo() : return); // use b"Michel Fortin" <michel.fortin michelf.com> wrote in message news:gn4pl9$1217$1 digitalmars.com...Dang! NullPointerException, because you never checked myObj against nullOn 2009-02-13 14:01:57 -0500, "Nick Sabalausky" <a a.a> said:-------- // This (a more generalized case of above)... Foo? myObj = ...; if(myObj !is null) { bar1(myObj); if(blah1 > blah2) myObj = null; // Yes, error bar2(); } // ...would change to this... Foo? myObj = ...; bool turnToNull=false; if(myObj !is null) { bar1(myObj); if(blah1 > blah2) turnToNull = true; } if(turnToNull) { myObj = null; bar2(); } --------Foo? myObj = ...; if (myObj !is null) { doSomethingWith(myObj); myObj = null; // should this be an error? }Or use an existing syntax: Foo? foo = ...; if (Foo value = foo) { // value is a local variable that is only accessible if foo is not null } else { // value is not accessible here }I could live with that, but I'd prefer my suggestion because it wouldn't require the creation of an extra label for what's essentially the same variable. With your code we'd just end up with a whole bunch of: Foo? myObj = ...; if (Foo nonnullMyObj = myObj) //etc... // or Foo? nullableMyObj = ...; if (Foo myObj = nullableMyObj) //etc... ...Which just seems unnecessary to me.And what about: Foo? myObj = ...; while (myObj !is null) myObj = myObj.next;-------- Foo? myObj = ...; while(true) { if(myObj.next !is null)myObj = myObj.next; else break; } myObj = null; //this line optional // Or, if you don't like "while(true)", // you could use a "bool done" flag. -------- With Denis's syntax, I'm not sure how the second one would be possible,Foo? myObj = ...; if (Foo obj = myObj) { while (true) { if (auto next = obj.next) { obj = next; } else { break; } } }but the first one would certainly be nicer. So I'm tempted to say that both syntaxes should be allowed... However, you do have a valid point that my syntax has a problem whenever assigning a possibly-null value to the original nullable variable from within the scope of the null-check. It can definitely be worked around, but I am coming to realize that maybe removing a variable's nullability shouldn't happen implicitly unless it can also be added back implicity - which would require flow analysis. Between that and the difficultly of Denis's syntax handling that simple while loop example, I guess full-blown flow-analysis would be needed after all in order to realistically eliminate null reference errors on nullable types. Dang!I don't think code flow analysis the way you suggest is useful. I certainly don't want my variable types to be changed at some point after null-check. Code flow analysis would be nice to have, but in a different way: Foo b; // not initialized, can not be read yet if (condition) { b = createFoo(42); } else if (otherCondition) { b = new Foo(); } else { // return b; // error, b is write only return; } // b is both read/write accessible at this point
Feb 14 2009
On Sat, 14 Feb 2009 15:42:57 +0300, Yigal Chripun <yigal100 gmail.com> wrote:Denis Koroskin wrote:It solves the simplest examples, but not more complex ones, so it is not generic enough.On Sat, 14 Feb 2009 11:39:17 +0300, Nick Sabalausky <a a.a> wrote:can't this be done with: Foo b = condition ? createFoo(42) : (otherCondition ? new Foo() : return); // use b"Michel Fortin" <michel.fortin michelf.com> wrote in message news:gn4pl9$1217$1 digitalmars.com...Dang! NullPointerException, because you never checked myObj against nullOn 2009-02-13 14:01:57 -0500, "Nick Sabalausky" <a a.a> said:-------- // This (a more generalized case of above)... Foo? myObj = ...; if(myObj !is null) { bar1(myObj); if(blah1 > blah2) myObj = null; // Yes, error bar2(); } // ...would change to this... Foo? myObj = ...; bool turnToNull=false; if(myObj !is null) { bar1(myObj); if(blah1 > blah2) turnToNull = true; } if(turnToNull) { myObj = null; bar2(); } --------Foo? myObj = ...; if (myObj !is null) { doSomethingWith(myObj); myObj = null; // should this be an error? }Or use an existing syntax: Foo? foo = ...; if (Foo value = foo) { // value is a local variable that is only accessible if foo is not null } else { // value is not accessible here }I could live with that, but I'd prefer my suggestion because it wouldn't require the creation of an extra label for what's essentially the same variable. With your code we'd just end up with a whole bunch of: Foo? myObj = ...; if (Foo nonnullMyObj = myObj) //etc... // or Foo? nullableMyObj = ...; if (Foo myObj = nullableMyObj) //etc... ...Which just seems unnecessary to me.And what about: Foo? myObj = ...; while (myObj !is null) myObj = myObj.next;-------- Foo? myObj = ...; while(true) { if(myObj.next !is null)myObj = myObj.next; else break; } myObj = null; //this line optional // Or, if you don't like "while(true)", // you could use a "bool done" flag. -------- With Denis's syntax, I'm not sure how the second one would be possible,Foo? myObj = ...; if (Foo obj = myObj) { while (true) { if (auto next = obj.next) { obj = next; } else { break; } } }but the first one would certainly be nicer. So I'm tempted to say that both syntaxes should be allowed... However, you do have a valid point that my syntax has a problem whenever assigning a possibly-null value to the original nullable variable from within the scope of the null-check. It can definitely be worked around, but I am coming to realize that maybe removing a variable's nullability shouldn't happen implicitly unless it can also be added back implicity - which would require flow analysis. Between that and the difficultly of Denis's syntax handling that simple while loop example, I guess full-blown flow-analysis would be needed after all in order to realistically eliminate null reference errors on nullable types. Dang!I don't think code flow analysis the way you suggest is useful. I certainly don't want my variable types to be changed at some point after null-check. Code flow analysis would be nice to have, but in a different way: Foo b; // not initialized, can not be read yet if (condition) { b = createFoo(42); } else if (otherCondition) { b = new Foo(); } else { // return b; // error, b is write only return; } // b is both read/write accessible at this point
Feb 14 2009
Denis Koroskin wrote:On Sat, 14 Feb 2009 15:42:57 +0300, Yigal Chripun <yigal100 gmail.com> wrote:In what way it's not generic enough? IMO, this is not a matter of flow analysis at all, but rather a matter of if statement syntax. IMO "if" needs to be expression instead of a statement. also See http://nemerle.org/Quick_Guide#DecisionsDenis Koroskin wrote:It solves the simplest examples, but not more complex ones, so it is not generic enough.On Sat, 14 Feb 2009 11:39:17 +0300, Nick Sabalausky <a a.a> wrote:can't this be done with: Foo b = condition ? createFoo(42) : (otherCondition ? new Foo() : return); // use b"Michel Fortin" <michel.fortin michelf.com> wrote in message news:gn4pl9$1217$1 digitalmars.com...Dang! NullPointerException, because you never checked myObj against nullOn 2009-02-13 14:01:57 -0500, "Nick Sabalausky" <a a.a> said:-------- // This (a more generalized case of above)... Foo? myObj = ...; if(myObj !is null) { bar1(myObj); if(blah1 > blah2) myObj = null; // Yes, error bar2(); } // ...would change to this... Foo? myObj = ...; bool turnToNull=false; if(myObj !is null) { bar1(myObj); if(blah1 > blah2) turnToNull = true; } if(turnToNull) { myObj = null; bar2(); } --------Foo? myObj = ...; if (myObj !is null) { doSomethingWith(myObj); myObj = null; // should this be an error? }Or use an existing syntax: Foo? foo = ...; if (Foo value = foo) { // value is a local variable that is only accessible if foo is not null } else { // value is not accessible here }I could live with that, but I'd prefer my suggestion because it wouldn't require the creation of an extra label for what's essentially the same variable. With your code we'd just end up with a whole bunch of: Foo? myObj = ...; if (Foo nonnullMyObj = myObj) //etc... // or Foo? nullableMyObj = ...; if (Foo myObj = nullableMyObj) //etc... ...Which just seems unnecessary to me.And what about: Foo? myObj = ...; while (myObj !is null) myObj = myObj.next;-------- Foo? myObj = ...; while(true) { if(myObj.next !is null)myObj = myObj.next; else break; } myObj = null; //this line optional // Or, if you don't like "while(true)", // you could use a "bool done" flag. -------- With Denis's syntax, I'm not sure how the second one would be possible,Foo? myObj = ...; if (Foo obj = myObj) { while (true) { if (auto next = obj.next) { obj = next; } else { break; } } }but the first one would certainly be nicer. So I'm tempted to say that both syntaxes should be allowed... However, you do have a valid point that my syntax has a problem whenever assigning a possibly-null value to the original nullable variable from within the scope of the null-check. It can definitely be worked around, but I am coming to realize that maybe removing a variable's nullability shouldn't happen implicitly unless it can also be added back implicity - which would require flow analysis. Between that and the difficultly of Denis's syntax handling that simple while loop example, I guess full-blown flow-analysis would be needed after all in order to realistically eliminate null reference errors on nullable types. Dang!I don't think code flow analysis the way you suggest is useful. I certainly don't want my variable types to be changed at some point after null-check. Code flow analysis would be nice to have, but in a different way: Foo b; // not initialized, can not be read yet if (condition) { b = createFoo(42); } else if (otherCondition) { b = new Foo(); } else { // return b; // error, b is write only return; } // b is both read/write accessible at this point
Feb 14 2009
Yigal Chripun:IMO "if" needs to be expression instead of a statement. also See http://nemerle.org/Quick_Guide#DecisionsIf you want to turn D into a more functional language, then that may be positive. But I think D will not change so much, so better for you to stick to things that are more likely to change. Bye, bearophile
Feb 14 2009
"bearophile" <bearophileHUGS lycos.com> wrote in message news:gn6ism$1rgc$1 digitalmars.com...Yigal Chripun:D's already becoming more functional. Evidence: pure, immutable, std.algorithm.IMO "if" needs to be expression instead of a statement. also See http://nemerle.org/Quick_Guide#DecisionsIf you want to turn D into a more functional language, then that may be positive. But I think D will not change so much, so better for you to stick to things that are more likely to change.
Feb 14 2009
Nick Sabalausky wrote:"bearophile" <bearophileHUGS lycos.com> wrote in message news:gn6ism$1rgc$1 digitalmars.com......std.functional. AndreiYigal Chripun:D's already becoming more functional. Evidence: pure, immutable, std.algorithm.IMO "if" needs to be expression instead of a statement. also See http://nemerle.org/Quick_Guide#DecisionsIf you want to turn D into a more functional language, then that may be positive. But I think D will not change so much, so better for you to stick to things that are more likely to change.
Feb 14 2009
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message news:gn7447$51u$1 digitalmars.com...Nick Sabalausky wrote:Sorry, I'm still in D1-land ;-)"bearophile" <bearophileHUGS lycos.com> wrote in message news:gn6ism$1rgc$1 digitalmars.com......std.functional. AndreiYigal Chripun:D's already becoming more functional. Evidence: pure, immutable, std.algorithm.IMO "if" needs to be expression instead of a statement. also See http://nemerle.org/Quick_Guide#DecisionsIf you want to turn D into a more functional language, then that may be positive. But I think D will not change so much, so better for you to stick to things that are more likely to change.
Feb 14 2009
Andrei Alexandrescu wrote:Nick Sabalausky wrote:Besides, such a change will allow us to remove the ugly ?: operator and will free the ? sign. One of my favorite Ruby features (besides Blocks) is that Ruby allows using ? and ! as part of identifiers. This is used in Ruby by convention to represent methods that answer questions, and methods that are more "dangareous" like in-place modification of data. so you can write: if (range.more?) .. and it also has array.sort vs. array.sort! where the former gives a sorted copy and the latter sorts in-place."bearophile" <bearophileHUGS lycos.com> wrote in message news:gn6ism$1rgc$1 digitalmars.com......std.functional. AndreiYigal Chripun:D's already becoming more functional. Evidence: pure, immutable, std.algorithm.IMO "if" needs to be expression instead of a statement. also See http://nemerle.org/Quick_Guide#DecisionsIf you want to turn D into a more functional language, then that may be positive. But I think D will not change so much, so better for you to stick to things that are more likely to change.
Feb 14 2009
"Yigal Chripun" <yigal100 gmail.com> wrote in message news:gn771i$ded$1 digitalmars.com...Besides, such a change will allow us to remove the ugly ?: operator and will free the ? sign.I like the ?: operator :-). It's short. But I agree it might be worth switching to an expression "if...else..." if that meant we could do the following...One of my favorite Ruby features (besides Blocks) is that Ruby allows using ? and ! as part of identifiers. This is used in Ruby by convention to represent methods that answer questions, and methods that are more "dangareous" like in-place modification of data. so you can write: if (range.more?) ..When I was looking into Ruby, I was impressed by this too. I had always liked MS's convention of prepending "is" to flags, but that only works on certain flags (sometimes you really mean "has" or "exists" or "capable of" something else besides "is"). Appending "?" is much more general.and it also has array.sort vs. array.sort! where the former gives a sorted copy and the latter sorts in-place.It would be kind of handy to have a nice simple convention for in-place vs non-inplace functions. Obviously "!" wouldn't work for D though, unless we were masochistic enough to revisit the old "What syntax to use for templates?" issue.
Feb 14 2009
Nick Sabalausky wrote:"Yigal Chripun"<yigal100 gmail.com> wrote in message news:gn771i$ded$1 digitalmars.com...well, IMO there are better syntax options for templates but I doubt it if it'll ever change, I remember that long thread about this very subject.. there's another way to mark in-place vs. copy which I don't like as much - I think it's used in Python: array.sort vs. array.sorted where the first form is in-place and the other is a copy. the convention is to use adjectives for copies - if you say array.sort (with a verb) you actually sort the *current* array. this is more fragile IMO than just using a "!" since you need to be familiar with English grammar. (for non-native English speakers that can be an issue) e.g: egg.rot vs. egg.rotten, etc..Besides, such a change will allow us to remove the ugly ?: operator and will free the ? sign.I like the ?: operator :-). It's short. But I agree it might be worth switching to an expression "if...else..." if that meant we could do the following...One of my favorite Ruby features (besides Blocks) is that Ruby allows using ? and ! as part of identifiers. This is used in Ruby by convention to represent methods that answer questions, and methods that are more "dangareous" like in-place modification of data. so you can write: if (range.more?) ..When I was looking into Ruby, I was impressed by this too. I had always liked MS's convention of prepending "is" to flags, but that only works on certain flags (sometimes you really mean "has" or "exists" or "capable of" something else besides "is"). Appending "?" is much more general.and it also has array.sort vs. array.sort! where the former gives a sorted copy and the latter sorts in-place.It would be kind of handy to have a nice simple convention for in-place vs non-inplace functions. Obviously "!" wouldn't work for D though, unless we were masochistic enough to revisit the old "What syntax to use for templates?" issue.
Feb 14 2009
"Denis Koroskin" <2korden gmail.com> wrote in message news:op.upcaojexo7cclz korden-pc...On Sat, 14 Feb 2009 11:39:17 +0300, Nick Sabalausky <a a.a> wrote:I blame fatigue ;) -------- Foo? myObj = ...; if(myObj !is null) { while(true) { if(myObj.next !is null) myObj = myObj.next; else break; } } myObj = null; //this line optional --------"Michel Fortin" <michel.fortin michelf.com> wrote in message news:gn4pl9$1217$1 digitalmars.com...Dang! NullPointerException, because you never checked myObj against nullOn 2009-02-13 14:01:57 -0500, "Nick Sabalausky" <a a.a> said:-------- // This (a more generalized case of above)... Foo? myObj = ...; if(myObj !is null) { bar1(myObj); if(blah1 > blah2) myObj = null; // Yes, error bar2(); } // ...would change to this... Foo? myObj = ...; bool turnToNull=false; if(myObj !is null) { bar1(myObj); if(blah1 > blah2) turnToNull = true; } if(turnToNull) { myObj = null; bar2(); } --------Foo? myObj = ...; if (myObj !is null) { doSomethingWith(myObj); myObj = null; // should this be an error? }Or use an existing syntax: Foo? foo = ...; if (Foo value = foo) { // value is a local variable that is only accessible if foo is not null } else { // value is not accessible here }I could live with that, but I'd prefer my suggestion because it wouldn't require the creation of an extra label for what's essentially the same variable. With your code we'd just end up with a whole bunch of: Foo? myObj = ...; if (Foo nonnullMyObj = myObj) //etc... // or Foo? nullableMyObj = ...; if (Foo myObj = nullableMyObj) //etc... ...Which just seems unnecessary to me.And what about: Foo? myObj = ...; while (myObj !is null) myObj = myObj.next;-------- Foo? myObj = ...; while(true) { if(myObj.next !is null)myObj = myObj.next; else break; } myObj = null; //this line optional // Or, if you don't like "while(true)", // you could use a "bool done" flag. --------I don't think code flow analysis the way you suggest is useful. I certainly don't want my variable types to be changed at some point after null-check.I'm not sure if we're on the same page here. What I was thinking about code flow analysis was this: Foo? maybeGetObj() {...} void takesAFoo(Foo f) {...} Foo? f = maybeGetObj(); // Ok, f *is* permanently "Foo?" f.mFunc(); // Illegal, might be null takesAFoo(f); // Illegal, might be null // Tells compiler f is now implicitly convertable to "Foo" if(f !is null) { f.mFunc(); // Ok takesAFoo(f); // Ok // With flow-analysis, this is ok and tells // compiler f is no longer implicitly // convertable to "Foo" f = maybeGetObj(); f.mFunc(); // Illegal takesAFoo(f); // Illegal f = new Foo(); // now implicitly convertable to "Foo" f.mFunc(); // Ok takesAFoo(f); // Ok // Ok, but possible warning that the condition's // result will always be the same (true in this case). if(f !is null) {...} f = null; // no longer implicitly convertable to "Foo" } else // f is still *not* implicitly convertable to "Foo" { f = new Foo(); // now implicitly convertable to "Foo" } // Depending which branch of the if was taken, // f might be implicitly convertable to "Foo", // or it might not be. So, from here, assume // that it *isn't* implicitly convertable to "Foo". Foo f2=...; // Ok, f2 *is* permanently "Foo" // Illegal, f2 *is* "Foo" f2 = null; // Error, comparison of incompatible types if(f2 !is null) {...}Code flow analysis would be nice to have, but in a different way: Foo b; // not initialized, can not be read yet if (condition) { b = createFoo(42); } else if (otherCondition) { b = new Foo(); } else { // return b; // error, b is write only return; } // b is both read/write accessible at this pointAgreed, that would be nice to have.
Feb 14 2009
Denis Koroskin wrote:[snip]Both of these syntaxes are solving a problem that doesn't exist. This is why we have null dereference exceptions: accessing a null pointer is an error. All this is doing is moving the onus for the check from the hardware to the programmer. Leave magic out of the language and let the hardware do it's job. If you have a nullable type, it's because you WANT it to be nullable, and you shouldn't have to stand on one leg and jump through a burning hoop every time you want to look at the damn thing. The point here is not to make using null harder, it's to make not using null easier. -- DanielI still like this that someone else mentioned: T? x = something; if(x !is null) { // x is implicitly "T" here, not "T?" } else { // handle null condition (x is still "T?") }Or use an existing syntax: Foo? foo = ...; if (Foo value = foo) { // value is a local variable that is only accessible if foo is not null } else { // value is not accessible here }
Feb 13 2009
On Fri, Feb 13, 2009 at 5:52 PM, Daniel Keep <daniel.keep.lists gmail.com> wrote:Both of these syntaxes are solving a problem that doesn't exist. This is why we have null dereference exceptions: accessing a null pointer is an error. All this is doing is moving the onus for the check from the hardware to the programmer. Leave magic out of the language and let the hardware do it's job. If you have a nullable type, it's because you WANT it to be nullable, and you shouldn't have to stand on one leg and jump through a burning hoop every time you want to look at the damn thing.Having only nullable references with no non-null counterpart is like a builder building houses with holes in the walls, whether the people who live in them want them or not, so that small animals can get in. Then the residents are forced to check that there are no small animals in their house all the time rather than just _not building the house with holes in the wall to begin with._ The hardware only has a job _to do_ because for decades languages have not been smart enough to prevent invalid pointers to begin with. You could even argue that letting the hardware catch null pointers is an abuse of what the virtual memory hardware is meant for - keeping processes from messing with each others' data, not ensuring program correctness. Ensuring program correctness is the compiler's job.
Feb 13 2009
Jarrett Billingsley wrote:On Fri, Feb 13, 2009 at 5:52 PM, Daniel Keep <daniel.keep.lists gmail.com> wrote:This is (expletive) ridiculous. Why is it that I'm unable to criticise even a tiny aspect of someone's proposal without people disregarding everything I've said TIME AND AGAIN over the past year or more that I'm in support of non-nullable references and go "oh but we need non-nullable references"?! It's like if I don't 100% agree with someone, I'm automatically completely opposed to their position. I'm opposed to having to check nullable types every goddamn time you want to look at its value. Screw it. -- DanielBoth of these syntaxes are solving a problem that doesn't exist. This is why we have null dereference exceptions: accessing a null pointer is an error. All this is doing is moving the onus for the check from the hardware to the programmer. Leave magic out of the language and let the hardware do it's job. If you have a nullable type, it's because you WANT it to be nullable, and you shouldn't have to stand on one leg and jump through a burning hoop every time you want to look at the damn thing.Having only nullable references with no non-null counterpart *SNAP*
Feb 13 2009
On Fri, Feb 13, 2009 at 10:16 PM, Daniel Keep <daniel.keep.lists gmail.com> wrote:This is (expletive) ridiculous. Why is it that I'm unable to criticise even a tiny aspect of someone's proposal without people disregarding everything I've said TIME AND AGAIN over the past year or more that I'm in support of non-nullable references and go "oh but we need non-nullable references"?!Oh...kay. That was kind of uncalled for. I'm sorry I don't keep tabs on the individual opinions of everyone on this newsgroup. It's particularly difficult to remember things about people when all I can see of them is their name.
Feb 13 2009
Sorry, Jarrett. You're right; it was uncalled for. I was having a bad day, and that was just the straw that broke the camel's back. My comments were slightly ambiguous, but I was still upset that trying to comment on a particular syntax or subfeature of non-nullable types results in me being chucked bodily into the "hates non-nullable types" camp. Again. :P To clarify: I am, and always have been, in full support of non-nullable types, preferably by default. What I object to specifically in this case is the requirement to always check that a nullable value is not null every time it is used. We have hardware null-dereference exceptions for this. Another issue is that this subthread is talking about increasingly more complicated analysis by the compiler to try and determine if a given nullable value has been checked yet or not. I don't think this is the job of the compiler; if I have a nullable value, it's because I wanted a nullable value, and I should be ready to deal with it appropriately. Finally, this also creates a distinction between nullable types and everything else in the type system. For example, the following test isn't enforced by the compiler. int a,b; // set a and b if( b != 0 ) int c = a / b; Maybe it should be, but unless the compiler is -very- smart about it AND it applies to all types that have potentially "unsafe" values for a given operation, I don't want to see nullable types singled out. -- Daniel
Feb 15 2009
Daniel Keep wrote:To clarify: I am, and always have been, in full support of non-nullable types, preferably by default. What I object to specifically in this case is the requirement to always check that a nullable value is not null every time it is used. We have hardware null-dereference exceptions for this. Another issue is that this subthread is talking about increasingly more complicated analysis by the compiler to try and determine if a given nullable value has been checked yet or not. I don't think this is the job of the compiler; if I have a nullable value, it's because I wanted a nullable value, and I should be ready to deal with it appropriately. Finally, this also creates a distinction between nullable types and everything else in the type system.I am in complete agreement with you on all these points. Nullable types (int? *) and making non-nullable the default would add huge benefits; but I think others are proposing significant complexity for very small extra gain.
Feb 16 2009
Mon, 16 Feb 2009 13:26:29 +1100, Daniel Keep wrote:To clarify: I am, and always have been, in full support of non-nullable types, preferably by default. What I object to specifically in this case is the requirement to always check that a nullable value is not null every time it is used.Hmm, I think I've got your point. The nullable types should work exactly as they work now, with the same consequences. You don't need to check for null to dereference, and you crash if you dereference null. The non-nullable types are a separate territory. Again, you don't need to check for null to dereference, and you never crash because there is never null. You need an explicit run-time check to move from null to non-null territory, but that's all you need, and only when you really want it. I think it's my favorite design so far.
Feb 16 2009
On Tue, 17 Feb 2009 06:03:45 +0300, Sergey Gromov wrote:I think it's my favorite design so far.i second that. this would be wonderful.
Feb 17 2009
Sergey Gromov wrote:Mon, 16 Feb 2009 13:26:29 +1100, Daniel Keep wrote:One possible change: implicit casting with an assertion that the nullable value is not null. I'm not sure whether this is a good idea. On the one hand, it's easier for the programmer to use nullable types in that case; on the other, it encourages people not to have error handling. I favor implicit casting, for now. It shouldn't be difficult to try it both ways.To clarify: I am, and always have been, in full support of non-nullable types, preferably by default. What I object to specifically in this case is the requirement to always check that a nullable value is not null every time it is used.Hmm, I think I've got your point. The nullable types should work exactly as they work now, with the same consequences. You don't need to check for null to dereference, and you crash if you dereference null. The non-nullable types are a separate territory. Again, you don't need to check for null to dereference, and you never crash because there is never null. You need an explicit run-time check to move from null to non-null territory, but that's all you need, and only when you really want it. I think it's my favorite design so far.
Feb 17 2009
"Christopher Wright" <dhasenan gmail.com> wrote in message news:gnfgj6$1484$2 digitalmars.com...One possible change: implicit casting with an assertion that the nullable value is not null.I can tell right now I wouldn't like that. That would make it far too easy to make mistakes, as it would open up a way for mistakes to circumvent the whole point of having non-nullables. If I accidentially tried to provide a nullable to something that expected a non-nullable, I'd want some sort of up-front notice so that I can either fix it or confirm "yes, I really did mean that" rather than have to hope that I'm lucky enough for the value to actually be null when I test it. An implicit cast should either "just work" with no risk of runtime-error, or be disallowed in favor of something more explicit.
Feb 17 2009
Nick Sabalausky wrote:"Christopher Wright" <dhasenan gmail.com> wrote in message news:gnfgj6$1484$2 digitalmars.com...I think I favor this, actually. If you don't care, you can cast manually. But the implementation difference should be miniscule.One possible change: implicit casting with an assertion that the nullable value is not null.I can tell right now I wouldn't like that. That would make it far too easy to make mistakes, as it would open up a way for mistakes to circumvent the whole point of having non-nullables. If I accidentially tried to provide a nullable to something that expected a non-nullable, I'd want some sort of up-front notice so that I can either fix it or confirm "yes, I really did mean that" rather than have to hope that I'm lucky enough for the value to actually be null when I test it. An implicit cast should either "just work" with no risk of runtime-error, or be disallowed in favor of something more explicit.
Feb 17 2009
Christopher Wright wrote:Nick Sabalausky wrote:One problem here is static constructors. They're supposed to run in import order, I believe, so if you do this: module A; Object o; static this () { o = new Object; } module B; import A; static this () { writeln(o); } That should be safe. I think. Class member variables are also problematic. It's probably going to be annoying to make sure each nullable variable gets initialized in every constructor. I could push that off to runtime, of course, but that isn't so great. Struct member variables are the killer, unless you have a struct constructor."Christopher Wright" <dhasenan gmail.com> wrote in message news:gnfgj6$1484$2 digitalmars.com...I think I favor this, actually. If you don't care, you can cast manually. But the implementation difference should be miniscule.One possible change: implicit casting with an assertion that the nullable value is not null.I can tell right now I wouldn't like that. That would make it far too easy to make mistakes, as it would open up a way for mistakes to circumvent the whole point of having non-nullables. If I accidentially tried to provide a nullable to something that expected a non-nullable, I'd want some sort of up-front notice so that I can either fix it or confirm "yes, I really did mean that" rather than have to hope that I'm lucky enough for the value to actually be null when I test it. An implicit cast should either "just work" with no risk of runtime-error, or be disallowed in favor of something more explicit.
Feb 18 2009
Christopher Wright wrote:One problem here is static constructors. They're supposed to run in import order, I believe, so if you do this: module A; Object o; static this () { o = new Object; } module B; import A; static this () { writeln(o); } That should be safe. I think. Class member variables are also problematic. It's probably going to be annoying to make sure each nullable variable gets initialized in every constructor. I could push that off to runtime, of course, but that isn't so great. Struct member variables are the killer, unless you have a struct constructor.Mmm... non-nullable types would also be the only type in D that cannot have it's own initialiser assigned to it. This is actually something I ran across trying to make a non-nullable struct; it can't be done because you can't force a variable to be non-default initialised. I'm not sure what the solution would be. A few thoughts: * Allow types to be flagged, within the compiler, as being "must-set." This includes all non-nullable types AND any aggregates that contain non-nullable types. If they're local variables, they have to be assigned to at declaration, and if they're members, the have to be assigned to within the constructor. * Make these types the exception and don't give them an init property. Generic code will either have to test for its absence, fail for non-nullable types, or be written differently. * Alternately, have an init property which is invalid and can't be assigned. Probably worse since you can't easily test for it. * If using the T? syntax to mean "nullable T," generic code could be written to use T? for all classes, then do the conversion to non-nullable at return time. * What should the following output? class T {} static if( is( T? : T ) ) pragma(msg, "T? : T"); static if( is( T : T? ) ) pragma(msg, "T : T?"); -- Daniel
Feb 18 2009
Daniel Keep wrote:Christopher Wright wrote:You could have the compiler use the default constructor to create an instance and assign that to Type.init, but that is evil.One problem here is static constructors. They're supposed to run in import order, I believe, so if you do this: module A; Object o; static this () { o = new Object; } module B; import A; static this () { writeln(o); } That should be safe. I think. Class member variables are also problematic. It's probably going to be annoying to make sure each nullable variable gets initialized in every constructor. I could push that off to runtime, of course, but that isn't so great. Struct member variables are the killer, unless you have a struct constructor.Mmm... non-nullable types would also be the only type in D that cannot have it's own initialiser assigned to it.This is actually something I ran across trying to make a non-nullable struct; it can't be done because you can't force a variable to be non-default initialised. I'm not sure what the solution would be. A few thoughts: * Allow types to be flagged, within the compiler, as being "must-set." This includes all non-nullable types AND any aggregates that contain non-nullable types. If they're local variables, they have to be assigned to at declaration, and if they're members, the have to be assigned to within the constructor.Determining this is a bit ugly...I think I said that.* Make these types the exception and don't give them an init property. Generic code will either have to test for its absence, fail for non-nullable types, or be written differently.No init property by default, but you could easily supply one. It wouldn't be CTFE-friendly, though.* Alternately, have an init property which is invalid and can't be assigned. Probably worse since you can't easily test for it.You can; see below. But the test isn't obvious.* If using the T? syntax to mean "nullable T," generic code could be written to use T? for all classes, then do the conversion to non-nullable at return time.Nullable seems to be a storage class. T? will be inconsistent as such. Additionally, I am certainly not going to implement nullable value inconsistent. One advantage of using "nullable T" rather than "T?" is IsExpressions: static if (is (T == nullable)) ... The alternative will probably be necessary, as well: static if (is (T U == nullable U)) ...* What should the following output? class T {} static if( is( T? : T ) ) pragma(msg, "T? : T"); static if( is( T : T? ) ) pragma(msg, "T : T?");T is implicitly convertible to nullable(T). There is some debate on whether the opposite should be allowed. So that will either print: T : T? or: T? : T T : T?
Feb 18 2009
On 2009-02-17 18:17:55 -0500, Christopher Wright <dhasenan gmail.com> said:One possible change: implicit casting with an assertion that the nullable value is not null. I'm not sure whether this is a good idea. On the one hand, it's easier for the programmer to use nullable types in that case; on the other, it encourages people not to have error handling.I think it's a good idea: good enough to be useful, simple enough to be implemented without much hassle. Once we have enough code using non-nullable, it'll be easier to evaluate the impacts of adding compile-time constrains for nullables, and whether it's worth it or not. I wouldn't make it just like an assertion though. I'd make it something separate you can deactiave with a compiler switch, just like bound checking. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Feb 17 2009
On Tue, Feb 17, 2009 at 10:36 PM, Michel Fortin <michel.fortin michelf.com> wrote:On 2009-02-17 18:17:55 -0500, Christopher Wright <dhasenan gmail.com> said:Actually each little debug check has a separate internal flag in the compiler. It just doesn't expose them all at that level of granularity. It just lets you turn them all on or all off. :POne possible change: implicit casting with an assertion that the nullable value is not null. I'm not sure whether this is a good idea. On the one hand, it's easier for the programmer to use nullable types in that case; on the other, it encourages people not to have error handling.I think it's a good idea: good enough to be useful, simple enough to be implemented without much hassle. Once we have enough code using non-nullable, it'll be easier to evaluate the impacts of adding compile-time constrains for nullables, and whether it's worth it or not. I wouldn't make it just like an assertion though. I'd make it something separate you can deactiave with a compiler switch, just like bound checking.
Feb 17 2009
"Daniel Keep" <daniel.keep.lists gmail.com> wrote in message news:gn4tjj$197g$1 digitalmars.com...Denis Koroskin wrote:The entire point of all of this is to make dereferencing null (and I mean an actual null, not "nullable") either difficult or (preferably) impossible. The reason we want to do that is that dereferencing null is a runtime error and we want to eliminate runtime errors whenever possible, by either eliminating their possiblity or by turning them into compile-time errors. Most null reference errors can be outright eliminated via non-null types, and the remaining cases can be turned into compile-time errors by forcing a check. Why would anyone want a runtime error when they could get a compile-time error instead? The "burning hoop", as you describe it, of checking a nullable var for null before dereferencing is just simply something that the programmer should already be doing anyway. Take the following case: void Foo(void delegate()? dg) //nullable { dg(); } If the programmer has a deliberate reason to *want* the dg paramater to be nullable, then why in the would would they ever want to dereference it like that without first checking for null? Just because they *want* their program to be spitting out runtime errors? I'm sorry, but I just don't buy that. (And the reason can't possibly be because they expected any possible nulls to be handled in the calling code, because that's exactly the type of scenario that non-nullables are intended for in the first place.) Also, just to be clear, no one (as far as I'm aware) is advocating anything like this: class Foo { private void delegate()? dg; // nullable public void setDg(void delegate()? dg) // nullable { if(dg !is null) // I don't think anyone is expecting this check to be required this.dg = dg; } } The forced check would only be on dereferencing and converting to non-nullable.[snip]Both of these syntaxes are solving a problem that doesn't exist. This is why we have null dereference exceptions: accessing a null pointer is an error. All this is doing is moving the onus for the check from the hardware to the programmer. Leave magic out of the language and let the hardware do it's job. If you have a nullable type, it's because you WANT it to be nullable, and you shouldn't have to stand on one leg and jump through a burning hoop every time you want to look at the damn thing. The point here is not to make using null harder, it's to make not using null easier.I still like this that someone else mentioned: T? x = something; if(x !is null) { // x is implicitly "T" here, not "T?" } else { // handle null condition (x is still "T?") }Or use an existing syntax: Foo? foo = ...; if (Foo value = foo) { // value is a local variable that is only accessible if foo is not null } else { // value is not accessible here }
Feb 13 2009
Nick Sabalausky wrote:The "burning hoop", as you describe it, of checking a nullable var for null before dereferencing is just simply something that the programmer should already be doing anyway. Take the following case: void Foo(void delegate()? dg) //nullable { dg(); }You're right for that small example. Now let's say you have an object a dozen methods referencing the same nullable member. They're private methods called by public methods that check if the member is null first. I don't want to have to check whether the variable is null every single time I use it; I want to do it once at the start and assume (since it's a single-threaded application and I'm not assigning to that member) that that check works for everything. I'm just fine with getting a segfault when using a nullable variable that's null. That's expected behavior.
Feb 14 2009
On Sat, Feb 14, 2009 at 8:37 AM, Christopher Wright <dhasenan gmail.com> wrote:....that's the entire point of non-null references. class Foo { private void delegate() dg; // non-null public this(void delegate()? dg) // nullable { if(dg !is null) this.dg = dg; // hey, dg must be non-null! else throw new Exception("NO! *SLAM*"); } private void method1() { // use dg here, and you're assured that it's non-null // all methods are guaranteed the same thing } } Why on earth would you rather use a nullable reference when you KNOW that it should never be null?void Foo(void delegate()? dg) //nullable { dg(); }You're right for that small example. Now let's say you have an object a dozen methods referencing the same nullable member. They're private methods called by public methods that check if the member is null first. I don't want to have to check whether the variable is null every single time I use it; I want to do it once at the start and assume (since it's a single-threaded application and I'm not assigning to that member) that that check works for everything.
Feb 14 2009
Jarrett Billingsley wrote:On Sat, Feb 14, 2009 at 8:37 AM, Christopher Wright <dhasenan gmail.com> wrote:No. I'm saying this class has a complex code path if some things are not null, and some other code path if they are null. It's quite valid if they are null, but I want to do other things if they aren't, and I don't want to cast constantly.....that's the entire point of non-null references.void Foo(void delegate()? dg) //nullable { dg(); }You're right for that small example. Now let's say you have an object a dozen methods referencing the same nullable member. They're private methods called by public methods that check if the member is null first. I don't want to have to check whether the variable is null every single time I use it; I want to do it once at the start and assume (since it's a single-threaded application and I'm not assigning to that member) that that check works for everything.
Feb 14 2009
"Christopher Wright" <dhasenan gmail.com> wrote in message news:gn704j$2s2u$1 digitalmars.com...Jarrett Billingsley wrote:You would only need to check when you're going to derefernce or convert to a non-nullable. Nulls could still be stored and passed around without checking. If this doesn't cover what you're concerned about, perhaps you could provide an example?On Sat, Feb 14, 2009 at 8:37 AM, Christopher Wright <dhasenan gmail.com> wrote:No. I'm saying this class has a complex code path if some things are not null, and some other code path if they are null. It's quite valid if they are null, but I want to do other things if they aren't, and I don't want to cast constantly.....that's the entire point of non-null references.void Foo(void delegate()? dg) //nullable { dg(); }You're right for that small example. Now let's say you have an object a dozen methods referencing the same nullable member. They're private methods called by public methods that check if the member is null first. I don't want to have to check whether the variable is null every single time I use it; I want to do it once at the start and assume (since it's a single-threaded application and I'm not assigning to that member) that that check works for everything.
Feb 14 2009
Nick Sabalausky wrote:You would only need to check when you're going to derefernce or convert to a non-nullable. Nulls could still be stored and passed around without checking. If this doesn't cover what you're concerned about, perhaps you could provide an example?Let's say I originally have this: class Foo { void delegate()? dg; void doStuff() { if (dg) { // some long code path with code duplicated from // other methods in Foo } else { // some other long code path } } } Now I want to refactor that: class Foo { void delegate()? dg; void doStuff() { if (dg) { doPart1; doPart2; } else { // some other long code path } } private void doPart1() { // use dg; why should I check? } private void doPart2() { // use dg; why should I check? } } Small examples don't show it very well.
Feb 14 2009
On Sun, 15 Feb 2009 02:22:17 +0300, Christopher Wright <dhasenan gmail.com> wrote:Nick Sabalausky wrote:private void doPart1() { void delegate() dg = unchecked(this.dg); // no checking done // use dg here without checking // *BUT* it someone denies the contract and calls the method without // ensuring that this.dg is not null, you'll get a access violation (or NPE) }You would only need to check when you're going to derefernce or convert to a non-nullable. Nulls could still be stored and passed around without checking. If this doesn't cover what you're concerned about, perhaps you could provide an example?Let's say I originally have this: class Foo { void delegate()? dg; void doStuff() { if (dg) { // some long code path with code duplicated from // other methods in Foo } else { // some other long code path } } } Now I want to refactor that: class Foo { void delegate()? dg; void doStuff() { if (dg) { doPart1; doPart2; } else { // some other long code path } } private void doPart1() { // use dg; why should I check? } private void doPart2() { // use dg; why should I check? } } Small examples don't show it very well.
Feb 14 2009
Denis Koroskin wrote:private void doPart1() { void delegate() dg = unchecked(this.dg); // no checking done // use dg here without checking // *BUT* it someone denies the contract and calls the method without // ensuring that this.dg is not null, you'll get a access violation (or NPE) }Fuck no.
Feb 14 2009
"Christopher Wright" <dhasenan gmail.com> wrote in message news:gn7jn9$1i0e$1 digitalmars.com...class Foo { void delegate()? dg; void doStuff() { if (dg) { doPart1; doPart2; } else { // some other long code path } } private void doPart1() { // use dg; why should I check?Because some other function or codepath could still accidentally be breaking your precondition convention, so you're right back to inviting hidden. The extra check prevents that. Also, in many cases (though not all), doPart1() might be better off being generalized like this: private void doPart1(ref void delegate() dg) { // Do stuff } ...or like this: private (void delegate()) doPart1(void delegate() dg) { // Do stuff return dg; }} private void doPart2() { // use dg; why should I check? } } Small examples don't show it very well.Denis Koroskin wrote:Agreed. Although my argument against it is that if you're going to bother to do that, you may as well just check for null anyway and save yourself the potential runtime error.private void doPart1() { void delegate() dg = unchecked(this.dg); // no checking done // use dg here without checking // *BUT* it someone denies the contract and calls the method without // ensuring that this.dg is not null, you'll get a access violation (or NPE) }Fuck no.
Feb 14 2009
"Nick Sabalausky" <a a.a> wrote in message news:gn7vef$2nb4$1 digitalmars.com...Because some other function or codepath could still accidentally be breaking your precondition convention, so you're right back to inviting hidden. TheSorry, that should be "...so you're right back to inviting hidden null reference errors."extra check prevents that. Also, in many cases (though not all), doPart1() might be better off being generalized like this:
Feb 14 2009
Nick Sabalausky wrote:"Christopher Wright" <dhasenan gmail.com> wrote in message news:gn7jn9$1i0e$1 digitalmars.com...Yes, but I'm using nullable variables. I'm happy with getting a hardware exception if I try dereferencing them when they're null. I could pass the non-nullable versions to each of these convenience functions, which works in small cases (one or two such variables) and totally eliminates the value of using member functions. Plus, that's code duplication. As for checking every time... It's code duplication. It's slower than removing the checks, and the checks aren't removed in release mode. The checks are all going to boil down to: if (variable) { } else { assert (false); } It's unnecessary. It's the compiler assuming that the programmer is an idiot and not allowing the programmer to insist that they know what they're doing. I want *warnings* about this. But I think it's going to require far too much boilerplate in complex circumstances.class Foo { void delegate()? dg; void doStuff() { if (dg) { doPart1; doPart2; } else { // some other long code path } } private void doPart1() { // use dg; why should I check?Because some other function or codepath could still accidentally be breaking your precondition convention, so you're right back to inviting hidden.
Feb 15 2009
"Christopher Wright" <dhasenan gmail.com> wrote in message news:gn96qc$2aic$1 digitalmars.com...I want *warnings* about this.Ok, now *that* I could live with (at least if we ever actually got the option to treat warnings AS warnings, but that's a whole other rant). Personally, I'd still prefer this particular thing to be an error rather than a warning (with an option to unsafe-cast it to a non-null for the rare case where the check is in an inner loop and might actually be a performance issue), but at least now I see your point.
Feb 15 2009
On 2009-02-14 08:37:04 -0500, Christopher Wright <dhasenan gmail.com> said:I'm just fine with getting a segfault when using a nullable variable that's null. That's expected behavior.I leaning to think it'd be best to have non-nullable pointers that just throw an exception when you attempt to assign null to them. That way you can have implicit conversions from nullable to non-nullable pointers where the compiler would add a check for null and throw; you no longer have to check for null for arguments that shouldn't be null (declaring the argument as non-nullable would force the caller to make sure it is not null, which cost nothing if the caller is passing a non-nullable variable); and you can catch incorrect assignment of null to non-nullable pointer before the assignment itself (instead of detecting it later it's too late). Non-nullable should still be the default because it's faster (no check for null) and safer to use, and I'd trust the optimiser to remove unnecessary checks for null when nullable pointers are casted to non-nullable ones (when you check yourself before casting for instance). -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Feb 14 2009
Daniel Keep wrote:Both of these syntaxes are solving a problem that doesn't exist. This is why we have null dereference exceptions: accessing a null pointer is an error. All this is doing is moving the onus for the check from the hardware to the programmer.I believe you should be able to use a nullable variable like its non-nullable counterpart. I am uncertain, but perhaps you should be able to implicitly cast to non-nullable, with an assertion added that the variable is not null. This gives you the safety of using non-nullable types and the ease of use of using nullable types.
Feb 14 2009
Nick Sabalausky wrote:I still like this that someone else mentioned: T? x = something; if(x !is null) { // x is implicitly "T" here, not "T?" } else { // handle null condition (x is still "T?") }I hate it. It encourages too much nesting, and it silently changes a variable's type.
Feb 14 2009
"Christopher Wright" <dhasenan gmail.com> wrote in message news:gn6h0r$1mk9$1 digitalmars.com...Nick Sabalausky wrote:You're right, I've come to realize that in a different branch of this thread.I still like this that someone else mentioned: T? x = something; if(x !is null) { // x is implicitly "T" here, not "T?" } else { // handle null condition (x is still "T?") }I hate it. It encourages too much nesting, and it silently changes a variable's type.
Feb 14 2009
Christopher Wright wrote:Or add an invariant. You know which field is null when it shouldn't be, so that should be simple enough. Or use a property rather than a field and add a contract.A runtime check is completely different from a compile time check. Sebastian
Feb 11 2009
Christopher Wright wrote:Sebastian Biallas wrote:Once your software is running, an easy to fix bug is just as bad as an hard to fix bug. It's a bug after all. Of course, you can ask the question whether it's worthwhile to alter the language. Well, for D this is still possible, while other languages will have NPEs till the end of the world.Christopher Wright wrote:Your language features should get rid of bugs that are easy to make and difficult to track down. It's not worthwhile to alter your language to remove easily found, easily fixed bugs.Oh, and I vote no. I think it's needless complexity. I code without any special care for null objects, and I get a segfault or NullReferenceException maybe once a week, probably less. I've always been able to track down the bug very quickly.That misses the point completely. It's not about you (as the programmer) getting NPEs; it's about the user getting bug-free software in the first place. In most cases a segfault/NPE is easy to track down for the programmer, I guess nobody would object to this. But once the software is shipped, it's a very serious problem: It's a situation the programmer didn't thought about so you usually have a data loss.Logic errors are difficult to find. Your language cannot help you eliminate those (though contracts and unittests can help you find them)."We shouldn't try to avoid bugs of type A because we can't avoid bugs of type B" is a logical fallacy.If you do not test your software extensively, you will ship software with logic errors. The testing required to find logic errors will also find low-level errors like segfaults.Uh.... sorry, but reality proves you wrong. I (and the rest of the world) get NPE in various kinds of extensively tested software. And we can get rid of *all* these errors by a simple language change (A change that should have been done centuries ago). This is a case where you can automatically proof correctness of a specific detail of your software. A chance that shouldn't be ignored because, uh, it's an easy to fix bug (If your rocket to the moon explodes because of an easy to fix bug, well, I don't think that is helps you that it was at least an easy to fix bug). Sebsatian
Feb 11 2009
Sebastian Biallas wrote:Christopher Wright wrote:Agreed. NPE are normally an easy to fix, easy to diagnose bug, but it can be *extremely* difficult to trigger a case when it occurs. Thus, trigger a run-time assert does not help AT ALL. Only a compile-time check will do.Sebastian Biallas wrote:Once your software is running, an easy to fix bug is just as bad as an hard to fix bug. It's a bug after all. Of course, you can ask the question whether it's worthwhile to alter the language. Well, for D this is still possible, while other languages will have NPEs till the end of the world.Christopher Wright wrote:Your language features should get rid of bugs that are easy to make and difficult to track down. It's not worthwhile to alter your language to remove easily found, easily fixed bugs.Oh, and I vote no. I think it's needless complexity. I code without any special care for null objects, and I get a segfault or NullReferenceException maybe once a week, probably less. I've always been able to track down the bug very quickly.That misses the point completely. It's not about you (as the programmer) getting NPEs; it's about the user getting bug-free software in the first place. In most cases a segfault/NPE is easy to track down for the programmer, I guess nobody would object to this. But once the software is shipped, it's a very serious problem: It's a situation the programmer didn't thought about so you usually have a data loss.Logic errors are difficult to find. Your language cannot help you eliminate those (though contracts and unittests can help you find them)."We shouldn't try to avoid bugs of type A because we can't avoid bugs of type B" is a logical fallacy.If you do not test your software extensively, you will ship software with logic errors. The testing required to find logic errors will also find low-level errors like segfaults.Uh.... sorry, but reality proves you wrong. I (and the rest of the world) get NPE in various kinds of extensively tested software. And we can get rid of *all* these errors by a simple language change (A change that should have been done centuries ago). This is a case where you can automatically proof correctness of a specific detail of your software. A chance that shouldn't be ignored because, uh, it's an easy to fix bug (If your rocket to the moon explodes because of an easy to fix bug, well, I don't think that is helps you that it was at least an easy to fix bug).
Feb 11 2009
On Thu, 12 Feb 2009 05:53:10 +0100, Don wrote:Thus, trigger a run-time assert does not help AT ALL. Only a compile-time check will do.i couldnt agree more. i think this would be a great addition to D. if the syntax for dealing with nullables is kept simple, i dont see any downside. Foo? f = getFoo(); f.doStuff(); // shouldnt compile if (f) f.doSomething(); // automatically usable
Feb 11 2009
Thus, trigger a run-time assert does not help AT ALL. Only a compile-time check will do.I wouldn't mind if the compiler only inserted assert()s for me. Having to write these assert()s all over _and_ to write the documentation comments, that a parameter must not be null, is the most annoying thing. Doing it at runtime could save us from very annoying compiler behavior, and also simplifies the compiler implementation. (Wasn't D supposed to be simple for the compiler writer? It seems everyone forgot that, even Walter.) By the way, I wouldn't suggest to make non-null the default. This would probably be too big of a language change. Instead, I'd propose to explicitly mark non-nullable reference with "!" (similar to "?").
Feb 12 2009
"grauzone" <none example.net> wrote in message news:gn18a4$2c9c$1 digitalmars.com...I've been wondering about that too, as I certainly see the value in easy-parsing. However, whenever the ideals of "better error prevention" and "easy parsing" collide, I would much rather see the priority placed on "better error prevention". And I especially don't want to see a potential compile-time error left as a run-time error just for the sake of easier parsing. If easy parsing was my biggest concern, I'd just use an early version of ECMAScript (and I hate ECMAScript, especially the earlier versions).Thus, trigger a run-time assert does not help AT ALL. Only a compile-time check will do.I wouldn't mind if the compiler only inserted assert()s for me. Having to write these assert()s all over _and_ to write the documentation comments, that a parameter must not be null, is the most annoying thing. Doing it at runtime could save us from very annoying compiler behavior, and also simplifies the compiler implementation. (Wasn't D supposed to be simple for the compiler writer? It seems everyone forgot that, even Walter.)By the way, I wouldn't suggest to make non-null the default. This would probably be too big of a language change. Instead, I'd propose to explicitly mark non-nullable reference with "!" (similar to "?").Another one of the points of D (unlike C++) is to avoid being buried under poor language design choices by not being afraid to break backwords compatibility when it's the only way to fix a problem in the language's design. I'm convinced that D hasn't reached a point where making nun-nullable the default would be too much of a problem.
Feb 12 2009
On Mon, 09 Feb 2009 04:19:55 +0000, Brian wrote:On Mon, 09 Feb 2009 04:25:55 +0300, Denis Koroskin wrote:well, at the very least id like to see a (optional) warning/error for uninitialized pointers. This way I can be certain there are absolutely zero null pointers unless the null keyword itself is used. A quick search for 'null' would be guaranteed to show all possibly null variables. I know I'm not the first to wish for such. (Does a warning exist yet that I don't know about?)So, let's ask the community: Would you like to see nullable types in D? http://www.micropoll.com/akira/mpview/539369-138652 (please, don't abuse by voting multiple time) Explain your reasoning in newsgroups. Thank you.i vote yes, i would absolutely love non-nullable types. in some cases i even use dummy objects to avoid null checks.
Feb 09 2009
On Mon, 09 Feb 2009 18:20:56 +0000, Brian wrote:well, at the very least id like to see a (optional) warning/error for uninitialized pointers. This way I can be certain there are absolutely zero null pointers unless the null keyword itself is used. A quick search for 'null' would be guaranteed to show all possibly null variables. I know I'm not the first to wish for such. (Does a warning exist yet that I don't know about?)just to clarify, this is what id like. given this code: void main() { Foo f; bar(null); } class Foo() {} void bar(Foo) {} $ dmd main.d Completed Successfully $ dmd -wnull main.d main.d(2): warning: variable 'f' is default initialized to null main.d(3): warning: passing null as argument to function expecting Foo To prevent the warnings, you would need to change main to this: void main() { Foo f = null; bar(cast(Foo)null); }
Feb 09 2009