digitalmars.D - Non-nullable references, again
- =?iso-8859-1?Q?Julio=20C=e9sar=20Carrascal=20Urquijo?= (8/15) Dec 30 2008 He then goes on to kill our hope of having this checks on any future ver...
- dsimcha (13/16) Dec 30 2008 Yes, but even if this is accurate, it's misleading. Very seldom are nul...
- Daniel Keep (30/48) Dec 30 2008 I find this counterpoint to be a bit iffy. The problem with null
- Denis Koroskin (9/69) Dec 31 2008 You took the idea slightly wrong. The default should be non-nullable,
- Don (2/97) Dec 31 2008 Wouldn't this cause ambiguity with the "?:" operator?
- Daniel Keep (6/19) Dec 31 2008 That's why I didn't suggest it. This wouldn't be the only
- Benji Smith (16/20) Dec 31 2008 At first, thought you might be right, and that there would some
- Daniel Keep (11/39) Dec 31 2008 Disclaimer: I'm not an expert on compilers. Plus, I just got up. :P
- Michel Fortin (11/21) Dec 31 2008 As far as I know, this can't be done with pointer declarations. Read thi...
- Daniel Keep (8/33) Dec 31 2008 I don't think so; I believe that unary vs. binary operators are
- Andrei Alexandrescu (4/45) Dec 31 2008 It's about a pointer declaration, not a pointer dereference, a la "int *...
- Benji Smith (38/82) Jan 01 2009 I could be wrong too. I've done a fair bit of this stuff, but I'm no
- Don (10/102) Jan 02 2009 case a?.b:c:
- Benji Smith (4/114) Jan 02 2009 Damn. I got so distracted with the ternary operator, I forgot about case...
- Michel Fortin (11/24) Jan 02 2009 How's this different from
- Jarrett Billingsley (2/8) Jan 02 2009 What the heck is ((a*).b)? * is not a postfix operator.
- Michel Fortin (8/24) Jan 02 2009 It is, kind of: if "a" is a type, postfix "*" makes it a pointer.
- Benji Smith (5/34) Jan 02 2009 Think of it like this:
- Michel Fortin (11/16) Jan 02 2009 Just like:
- Don (8/26) Jan 02 2009 That's encouraging. I wasn't able to find any other ambiguous situations...
- Daniel Keep (10/22) Dec 31 2008 I didn't suggest that because it would require semantically breaking all...
- bearophile (4/7) Dec 31 2008 That syntax is now used by various other languages, it's slowly becoming...
It has been discussed before but I'd still love to see non-nullable references on D. Here's Anders Hejlsberg position on the subject.platform, and the same is true of Java for that matter, are probably null reference exceptions. If we had had a stronger type system that would allow you to say that 'this parameter may never be null, and you compiler please check that at every call, by doing static analysis of the code'. Then we could have stamped out classes of bugs.He then goes on to kill our hope of having this checks on any future version This is a change that will break lots of code but I think it will benefit the language and quality of D applications. Is it at least been looked at for D 3.0? Thanks
Dec 30 2008
Yes, but even if this is accurate, it's misleading. Very seldom are null references difficult-to-find, time-consuming bugs. Most other things in D and other languages that are designed to prevent specific classes of bugs are designed to prevent extremely aggravating, hard to track down bugs. For example, GC was invented because tracking down memory leaks is a huge PITA. Bounds checking was invented because off-by-one errors can be subtle and hard to find. Null reference errors, on the other hand, manifest themselves in a predictable way (segfaults), and if you're using the safe memory model, i.e. bounds checking, no pointers, that's about the only thing a segfault could mean. Furthermore, null checking could be added to an implementation kind of like bounds checking without changing the language spec. I haven't made up my mind fully yet, but I question whether adding lots of complexity to the language to prevent a very easy to track down class of bugs, even if it's a common one, is justified.platform, and the same is true of Java for that matter, are probably null reference exceptions.
Dec 30 2008
dsimcha wrote:I find this counterpoint to be a bit iffy. The problem with null dereference problems isn't knowing that they're there: that's the easy part. You helpfully get an exception to the face when that happens. The hard part is figuring out *where* the problem originally occurred. It's not when the exception is thrown that's the issue; it's the point at which you placed a null reference in a slot where you shouldn't have. Yes, we have invariants and contracts; but inevitably you're going to forget one, and it's that one slip-up that's going to bite you in the rear. One could use roughly the same argument for non-null references as for const: you could document it, but documentation is inevitably wrong or out of date. :P That said, I wonder what's stopping us from implementing them today. Last time I checked (admittedly, that was like a year ago) we didn't have the compile-time magic necessary to completely and transparently proxy any given object. Ideally, we should be able to do this: class Foo { void bar() { writefln("OH HAI WURLD!"); } } NonNull!(Foo) foo = new Foo; foo.bar(); Foo baz = foo; Off the top of my head, NonNull would require an opAssign, opImplicitCast to the templated type, and a way to build a full proxy of the underlying type. It also just occured to me that this would probably break scope. Damn. A nicer syntax would be appreciated, but probably isn't a requirement. :) -- DanielYes, but even if this is accurate, it's misleading. Very seldom are null references difficult-to-find, time-consuming bugs. Most other things in D and other languages that are designed to prevent specific classes of bugs are designed to prevent extremely aggravating, hard to track down bugs. For example, GC was invented because tracking down memory leaks is a huge PITA. Bounds checking was invented because off-by-one errors can be subtle and hard to find. Null reference errors, on the other hand, manifest themselves in a predictable way (segfaults), and if you're using the safe memory model, i.e. bounds checking, no pointers, that's about the only thing a segfault could mean. Furthermore, null checking could be added to an implementation kind of like bounds checking without changing the language spec. I haven't made up my mind fully yet, but I question whether adding lots of complexity to the language to prevent a very easy to track down class of bugs, even if it's a common one, is justified.platform, and the same is true of Java for that matter, are probably null reference exceptions.
Dec 30 2008
On Wed, 31 Dec 2008 08:37:56 +0300, Daniel Keep <daniel.keep.lists gmail.com> wrote:dsimcha wrote:You took the idea slightly wrong. The default should be non-nullable, Foo foo = null; // error Nullable!(Foo) foo2 = null; // ok No implicit conversion is possible from Nullable!(Foo) to Foo (unless one that throws an Exception on null-reference, but I believe it contradicts the very idea of non-null references).I find this counterpoint to be a bit iffy. The problem with null dereference problems isn't knowing that they're there: that's the easy part. You helpfully get an exception to the face when that happens. The hard part is figuring out *where* the problem originally occurred. It's not when the exception is thrown that's the issue; it's the point at which you placed a null reference in a slot where you shouldn't have. Yes, we have invariants and contracts; but inevitably you're going to forget one, and it's that one slip-up that's going to bite you in the rear. One could use roughly the same argument for non-null references as for const: you could document it, but documentation is inevitably wrong or out of date. :P That said, I wonder what's stopping us from implementing them today. Last time I checked (admittedly, that was like a year ago) we didn't have the compile-time magic necessary to completely and transparently proxy any given object. Ideally, we should be able to do this: class Foo { void bar() { writefln("OH HAI WURLD!"); } } NonNull!(Foo) foo = new Foo; foo.bar(); Foo baz = foo; Off the top of my head, NonNull would require an opAssign, opImplicitCast to the templated type, and a way to build a full proxy of the underlying type.Yes, but even if this is accurate, it's misleading. Very seldom are null references difficult-to-find, time-consuming bugs. Most other things in D and other languages that are designed to prevent specific classes of bugs are designed to prevent extremely aggravating, hard to track down bugs. For example, GC was invented because tracking down memory leaks is a huge PITA. Bounds checking was invented because off-by-one errors can be subtle and hard to find. Null reference errors, on the other hand, manifest themselves in a predictable way (segfaults), and if you're using the safe memory model, i.e. bounds checking, no pointers, that's about the only thing a segfault could mean. Furthermore, null checking could be added to an implementation kind of like bounds checking without changing the language spec. I haven't made up my mind fully yet, but I question whether adding lots of complexity to the language to prevent a very easy to track down class of bugs, even if it's a common one, is justified.platform, and the same is true of Java for that matter, are probably null reference exceptions.It also just occured to me that this would probably break scope. Damn.Scope is not broken. Quite the contrary, it goes on par with its meaning - scope variable can't be null-initialized (it makes no sense at least).A nicer syntax would be appreciated, but probably isn't a requirement. :) -- DanielFoo nonNull = new Foo(); Foo? possiblyNull = null;
Dec 31 2008
Denis Koroskin wrote:On Wed, 31 Dec 2008 08:37:56 +0300, Daniel Keep <daniel.keep.lists gmail.com> wrote:Wouldn't this cause ambiguity with the "?:" operator?dsimcha wrote:You took the idea slightly wrong. The default should be non-nullable, Foo foo = null; // error Nullable!(Foo) foo2 = null; // ok No implicit conversion is possible from Nullable!(Foo) to Foo (unless one that throws an Exception on null-reference, but I believe it contradicts the very idea of non-null references).I find this counterpoint to be a bit iffy. The problem with null dereference problems isn't knowing that they're there: that's the easy part. You helpfully get an exception to the face when that happens. The hard part is figuring out *where* the problem originally occurred. It's not when the exception is thrown that's the issue; it's the point at which you placed a null reference in a slot where you shouldn't have. Yes, we have invariants and contracts; but inevitably you're going to forget one, and it's that one slip-up that's going to bite you in the rear. One could use roughly the same argument for non-null references as for const: you could document it, but documentation is inevitably wrong or out of date. :P That said, I wonder what's stopping us from implementing them today. Last time I checked (admittedly, that was like a year ago) we didn't have the compile-time magic necessary to completely and transparently proxy any given object. Ideally, we should be able to do this: class Foo { void bar() { writefln("OH HAI WURLD!"); } } NonNull!(Foo) foo = new Foo; foo.bar(); Foo baz = foo; Off the top of my head, NonNull would require an opAssign, opImplicitCast to the templated type, and a way to build a full proxy of the underlying type.Yes, but even if this is accurate, it's misleading. Very seldom are null references difficult-to-find, time-consuming bugs. Most other things in D and other languages that are designed to prevent specific classes of bugs are designed to prevent extremely aggravating, hard to track down bugs. For example, GC was invented because tracking down memory leaks is a huge PITA. Bounds checking was invented because off-by-one errors can be subtle and hard to find. Null reference errors, on the other hand, manifest themselves in a predictable way (segfaults), and if you're using the safe memory model, i.e. bounds checking, no pointers, that's about the only thing a segfault could mean. Furthermore, null checking could be added to an implementation kind of like bounds checking without changing the language spec. I haven't made up my mind fully yet, but I question whether adding lots of complexity to the language to prevent a very easy to track down class of bugs, even if it's a common one, is justified.platform, and the same is true of Java for that matter, are probably null reference exceptions.It also just occured to me that this would probably break scope. Damn.Scope is not broken. Quite the contrary, it goes on par with its meaning - scope variable can't be null-initialized (it makes no sense at least).A nicer syntax would be appreciated, but probably isn't a requirement. :) -- DanielFoo nonNull = new Foo(); Foo? possiblyNull = null;
Dec 31 2008
Don wrote:Denis Koroskin wrote: [snip]That's why I didn't suggest it. This wouldn't be the only I think " " and "%" are still up for grabs, but aren't particularly attractive... -- DanielWouldn't this cause ambiguity with the "?:" operator?A nicer syntax would be appreciated, but probably isn't a requirement. :) -- DanielFoo nonNull = new Foo(); Foo? possiblyNull = null;
Dec 31 2008
Don wrote:Denis Koroskin wrote:At first, thought you might be right, and that there would some ambiguity calling constructors of nullable classes (especially given optional parentheses). But for the life of me, I couldn't come up with a truly ambiguous example, that couldn't be resolved with an extra token or two of lookahead. The '?' nullable-type operator is only used in type declarations, not in expressions, and the '?:' operator always consumes a few trailing expressions. nullable objects to either a non-null instance or a default value) looks like this: MyClass? myNullableObj = getNullableFromSomewhere(); MyClass myNonNullObj = myNullableObj ?? DEFAULT_VALUE; Since the double-hook is a single token, it's also unambiguous to parse. --benjiFoo nonNull = new Foo(); Foo? possiblyNull = null;Wouldn't this cause ambiguity with the "?:" operator?
Dec 31 2008
Benji Smith wrote:Don wrote:Disclaimer: I'm not an expert on compilers. Plus, I just got up. :P The key is that the parser has to know what "MyClass" means before it can figure out what the "?" is for; that's why it's context-dependant. D avoids this dependency between compilation stages, because it complicates the compiler. When the parser sees "MyClass", it *doesn't know* that it's a type, so it can't distinguish between a nullable type and an invalid ?: expression. At least, I think that's how it works; someone feel free to correct me if it's not. :P -- DanielDenis Koroskin wrote:>Foo nonNull = new Foo(); Foo? possiblyNull = null;Wouldn't this cause ambiguity with the "?:" operator?At first, thought you might be right, and that there would some ambiguity calling constructors of nullable classes (especially given optional parentheses). But for the life of me, I couldn't come up with a truly ambiguous example, that couldn't be resolved with an extra token or two of lookahead. The '?' nullable-type operator is only used in type declarations, not in expressions, and the '?:' operator always consumes a few trailing expressions. nullable objects to either a non-null instance or a default value) looks like this: MyClass? myNullableObj = getNullableFromSomewhere(); MyClass myNonNullObj = myNullableObj ?? DEFAULT_VALUE; Since the double-hook is a single token, it's also unambiguous to parse. --benji
Dec 31 2008
On 2008-12-31 21:50:53 -0500, Daniel Keep <daniel.keep.lists gmail.com> said:Disclaimer: I'm not an expert on compilers. Plus, I just got up. :P The key is that the parser has to know what "MyClass" means before it can figure out what the "?" is for; that's why it's context-dependant. D avoids this dependency between compilation stages, because it complicates the compiler. When the parser sees "MyClass", it *doesn't know* that it's a type, so it can't distinguish between a nullable type and an invalid ?: expression.As far as I know, this can't be done with pointer declarations. Read this: a * b; Is it a multiplication or a declaration of a pointer to type "a"? You don't know until you resolve the identifiers. It's the exact same situation for using "?" to denote nullable.At least, I think that's how it works; someone feel free to correct me if it's not. :PI belived the same for some time too, then found the above rebutal. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Dec 31 2008
Michel Fortin wrote:On 2008-12-31 21:50:53 -0500, Daniel Keep <daniel.keep.lists gmail.com> said:I don't think so; I believe that unary vs. binary operators are unambiguous. "a * b" is "a multiply b" because it's "(expr) * (expr)". It's pointer dereference when it's "* (expr)". I keep in mind is that "(expr) < (expr) >" is ambiguous, but "* (expr)" isn't. Like I said, I'm not an expert, so take what I say with a grain of salt. -- DanielDisclaimer: I'm not an expert on compilers. Plus, I just got up. :P The key is that the parser has to know what "MyClass" means before it can figure out what the "?" is for; that's why it's context-dependant. D avoids this dependency between compilation stages, because it complicates the compiler. When the parser sees "MyClass", it *doesn't know* that it's a type, so it can't distinguish between a nullable type and an invalid ?: expression.As far as I know, this can't be done with pointer declarations. Read this: a * b; Is it a multiplication or a declaration of a pointer to type "a"? You don't know until you resolve the identifiers. It's the exact same situation for using "?" to denote nullable.At least, I think that's how it works; someone feel free to correct me if it's not. :PI belived the same for some time too, then found the above rebutal.
Dec 31 2008
Daniel Keep wrote:Michel Fortin wrote:It's about a pointer declaration, not a pointer dereference, a la "int * p;" Happy New Year everyone! AndreiOn 2008-12-31 21:50:53 -0500, Daniel Keep <daniel.keep.lists gmail.com> said:I don't think so; I believe that unary vs. binary operators are unambiguous. "a * b" is "a multiply b" because it's "(expr) * (expr)". It's pointer dereference when it's "* (expr)". I keep in mind is that "(expr) < (expr) >" is ambiguous, but "* (expr)" isn't. Like I said, I'm not an expert, so take what I say with a grain of salt. -- DanielDisclaimer: I'm not an expert on compilers. Plus, I just got up. :P The key is that the parser has to know what "MyClass" means before it can figure out what the "?" is for; that's why it's context-dependant. D avoids this dependency between compilation stages, because it complicates the compiler. When the parser sees "MyClass", it *doesn't know* that it's a type, so it can't distinguish between a nullable type and an invalid ?: expression.As far as I know, this can't be done with pointer declarations. Read this: a * b; Is it a multiplication or a declaration of a pointer to type "a"? You don't know until you resolve the identifiers. It's the exact same situation for using "?" to denote nullable.At least, I think that's how it works; someone feel free to correct me if it's not. :PI belived the same for some time too, then found the above rebutal.
Dec 31 2008
Daniel Keep wrote:Benji Smith wrote:I could be wrong too. I've done a fair bit of this stuff, but I'm no expert either :) Nevertheless, I still don't think there's any ambiguity, as long as the parser can perform syntactic lookahead predicates. The grammar would look something like this: DECLARATION := IDENTIFIER // Type name ( HOOK )? // Is nullable? IDENTIFIER // Var name ( SEMICOLON // End of declaration | ( OP_ASSIGN // Assignment operator EXPRESSION // Assigned value ) ) Whereas the ternary expression grammar would look something like this: TERNARY_EXPRESSION := IDENTIFIER // Type name HOOK // Start of '?:' operator EXPRESSION // Value if true COLON // End of '?:' operator EXPRESSION // Value if false The only potential ambiguity arises because the "value if true" expression could also just be an identifier. But if the parser can construct syntactic predicates to perform LL(k) lookahead with arbitrary k, then it can just keep consuming tokens until it finds either a SEMICOLON, an OP_ASSIGN, or a COLON (potentially, recursively, if it encounters another identifier and hook within the expression). Still, though, once it finds one of those tokens, the syntax has been successfully disambiguated, without resorting to a semantic predicate. It requires arbitrary lookahead, but it can be done within a context-free grammar, and all within the syntax-processing portion of the parser. Of course, I could be completely wrong too :) --benjiDon wrote:Disclaimer: I'm not an expert on compilers. Plus, I just got up. :P The key is that the parser has to know what "MyClass" means before it can figure out what the "?" is for; that's why it's context-dependant. D avoids this dependency between compilation stages, because it complicates the compiler. When the parser sees "MyClass", it *doesn't know* that it's a type, so it can't distinguish between a nullable type and an invalid ?: expression. At least, I think that's how it works; someone feel free to correct me if it's not. :P -- DanielDenis Koroskin wrote:>Foo nonNull = new Foo(); Foo? possiblyNull = null;Wouldn't this cause ambiguity with the "?:" operator?At first, thought you might be right, and that there would some ambiguity calling constructors of nullable classes (especially given optional parentheses). But for the life of me, I couldn't come up with a truly ambiguous example, that couldn't be resolved with an extra token or two of lookahead. The '?' nullable-type operator is only used in type declarations, not in expressions, and the '?:' operator always consumes a few trailing expressions. nullable objects to either a non-null instance or a default value) looks like this: MyClass? myNullableObj = getNullableFromSomewhere(); MyClass myNonNullObj = myNullableObj ?? DEFAULT_VALUE; Since the double-hook is a single token, it's also unambiguous to parse. --benji
Jan 01 2009
Benji Smith wrote:Daniel Keep wrote:case a?.b:c: break; is this case ((a?).b): c: break; or is it case (a ? b : c ) : break;Benji Smith wrote:I could be wrong too. I've done a fair bit of this stuff, but I'm no expert either :) Nevertheless, I still don't think there's any ambiguity, as long as the parser can perform syntactic lookahead predicates. The grammar would look something like this: DECLARATION := IDENTIFIER // Type name ( HOOK )? // Is nullable? IDENTIFIER // Var name ( SEMICOLON // End of declaration | ( OP_ASSIGN // Assignment operator EXPRESSION // Assigned value ) ) Whereas the ternary expression grammar would look something like this: TERNARY_EXPRESSION := IDENTIFIER // Type name HOOK // Start of '?:' operator EXPRESSION // Value if true COLON // End of '?:' operator EXPRESSION // Value if false The only potential ambiguity arises because the "value if true" expression could also just be an identifier. But if the parser can construct syntactic predicates to perform LL(k) lookahead with arbitrary k, then it can just keep consuming tokens until it finds either a SEMICOLON, an OP_ASSIGN, or a COLON (potentially, recursively, if it encounters another identifier and hook within the expression). Still, though, once it finds one of those tokens, the syntax has been successfully disambiguated, without resorting to a semantic predicate. It requires arbitrary lookahead, but it can be done within a context-free grammar, and all within the syntax-processing portion of the parser. Of course, I could be completely wrong too :) --benjiDon wrote:Disclaimer: I'm not an expert on compilers. Plus, I just got up. :P The key is that the parser has to know what "MyClass" means before it can figure out what the "?" is for; that's why it's context-dependant. D avoids this dependency between compilation stages, because it complicates the compiler. When the parser sees "MyClass", it *doesn't know* that it's a type, so it can't distinguish between a nullable type and an invalid ?: expression. At least, I think that's how it works; someone feel free to correct me if it's not. :P -- DanielDenis Koroskin wrote:>Foo nonNull = new Foo(); Foo? possiblyNull = null;Wouldn't this cause ambiguity with the "?:" operator?At first, thought you might be right, and that there would some ambiguity calling constructors of nullable classes (especially given optional parentheses). But for the life of me, I couldn't come up with a truly ambiguous example, that couldn't be resolved with an extra token or two of lookahead. The '?' nullable-type operator is only used in type declarations, not in expressions, and the '?:' operator always consumes a few trailing expressions. nullable objects to either a non-null instance or a default value) looks like this: MyClass? myNullableObj = getNullableFromSomewhere(); MyClass myNonNullObj = myNullableObj ?? DEFAULT_VALUE; Since the double-hook is a single token, it's also unambiguous to parse. --benji
Jan 02 2009
Don wrote:Benji Smith wrote:Damn. I got so distracted with the ternary operator, I forgot about case statements. --benjiDaniel Keep wrote:case a?.b:c: break; is this case ((a?).b): c: break; or is it case (a ? b : c ) : break;Benji Smith wrote:I could be wrong too. I've done a fair bit of this stuff, but I'm no expert either :) Nevertheless, I still don't think there's any ambiguity, as long as the parser can perform syntactic lookahead predicates. The grammar would look something like this: DECLARATION := IDENTIFIER // Type name ( HOOK )? // Is nullable? IDENTIFIER // Var name ( SEMICOLON // End of declaration | ( OP_ASSIGN // Assignment operator EXPRESSION // Assigned value ) ) Whereas the ternary expression grammar would look something like this: TERNARY_EXPRESSION := IDENTIFIER // Type name HOOK // Start of '?:' operator EXPRESSION // Value if true COLON // End of '?:' operator EXPRESSION // Value if false The only potential ambiguity arises because the "value if true" expression could also just be an identifier. But if the parser can construct syntactic predicates to perform LL(k) lookahead with arbitrary k, then it can just keep consuming tokens until it finds either a SEMICOLON, an OP_ASSIGN, or a COLON (potentially, recursively, if it encounters another identifier and hook within the expression). Still, though, once it finds one of those tokens, the syntax has been successfully disambiguated, without resorting to a semantic predicate. It requires arbitrary lookahead, but it can be done within a context-free grammar, and all within the syntax-processing portion of the parser. Of course, I could be completely wrong too :) --benjiDon wrote:Disclaimer: I'm not an expert on compilers. Plus, I just got up. :P The key is that the parser has to know what "MyClass" means before it can figure out what the "?" is for; that's why it's context-dependant. D avoids this dependency between compilation stages, because it complicates the compiler. When the parser sees "MyClass", it *doesn't know* that it's a type, so it can't distinguish between a nullable type and an invalid ?: expression. At least, I think that's how it works; someone feel free to correct me if it's not. :P -- DanielDenis Koroskin wrote:>Foo nonNull = new Foo(); Foo? possiblyNull = null;Wouldn't this cause ambiguity with the "?:" operator?At first, thought you might be right, and that there would some ambiguity calling constructors of nullable classes (especially given optional parentheses). But for the life of me, I couldn't come up with a truly ambiguous example, that couldn't be resolved with an extra token or two of lookahead. The '?' nullable-type operator is only used in type declarations, not in expressions, and the '?:' operator always consumes a few trailing expressions. nullable objects to either a non-null instance or a default value) looks like this: MyClass? myNullableObj = getNullableFromSomewhere(); MyClass myNonNullObj = myNullableObj ?? DEFAULT_VALUE; Since the double-hook is a single token, it's also unambiguous to parse. --benji
Jan 02 2009
On 2009-01-02 10:37:50 -0500, Benji Smith <dlanguage benjismith.net> said:How's this different from case a*.b: is this: case ((a*).b): or is it: case ((a) * (.b)): -- Michel Fortin michel.fortin michelf.com http://michelf.com/case a?.b:c: break; is this case ((a?).b): c: break; or is it case (a ? b : c ) : break;
Jan 02 2009
On Fri, Jan 2, 2009 at 8:35 PM, Michel Fortin <michel.fortin michelf.com> wrote:How's this different from case a*.b: is this: case ((a*).b): or is it: case ((a) * (.b)):What the heck is ((a*).b)? * is not a postfix operator.
Jan 02 2009
On 2009-01-02 20:44:21 -0500, "Jarrett Billingsley" <jarrett.billingsley gmail.com> said:On Fri, Jan 2, 2009 at 8:35 PM, Michel Fortin <michel.fortin michelf.com> wrote:It is, kind of: if "a" is a type, postfix "*" makes it a pointer. If you test it, it'll compile if "a" is a struct having a member "b". -- Michel Fortin michel.fortin michelf.com http://michelf.com/How's this different from case a*.b: is this: case ((a*).b): or is it: case ((a) * (.b)):What the heck is ((a*).b)? * is not a postfix operator.
Jan 02 2009
Michel Fortin wrote:On 2009-01-02 10:37:50 -0500, Benji Smith <dlanguage benjismith.net> said:Think of it like this: MyClass?.myProperty It's a static field of the nullable MyClass type. --benjiHow's this different from case a*.b: is this: case ((a*).b): or is it: case ((a) * (.b)):case a?.b:c: break; is this case ((a?).b): c: break; or is it case (a ? b : c ) : break;
Jan 02 2009
On 2009-01-02 21:39:52 -0500, Benji Smith <dlanguage benjismith.net> said:Think of it like this: MyClass?.myProperty It's a static field of the nullable MyClass type.Just like: MyStruct*.myProperty It's a static field of the struct for which you have a pointer to. Exact that for it to compile, you need to write: (MyStruct*).myProperty I propose we do things the same way for "?". -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jan 02 2009
Michel Fortin wrote:On 2009-01-02 21:39:52 -0500, Benji Smith <dlanguage benjismith.net> said:That's encouraging. I wasn't able to find any other ambiguous situations (and the one I did find was very obscure); and it does seem (as you pointed out) that ambiguities with a*b are far more common. It would be an awesome feature IMHO. Null class references are by far the most common bug I make in D. And despite what people have said, working out why a class is null is not always easy, especially when it only shows up rarely in production code.Think of it like this: MyClass?.myProperty It's a static field of the nullable MyClass type.Just like: MyStruct*.myProperty It's a static field of the struct for which you have a pointer to. Exact that for it to compile, you need to write: (MyStruct*).myProperty I propose we do things the same way for "?".
Jan 02 2009
Denis Koroskin wrote:[snip] You took the idea slightly wrong. The default should be non-nullable, Foo foo = null; // error Nullable!(Foo) foo2 = null; // okI didn't suggest that because it would require semantically breaking all existing OOP code in D. I went with a proxy struct idea since that could conceivably be implemented in a library, and provide a stepping stone to full non-nullable by default.[snip]I was referring to the case of using a proxy struct. scope NonNull!(Foo) bar = new Foo; AFAIK, this wouldn't have the desired behaviour (auto-collecting bar at the end of scope.) -- DanielIt also just occured to me that this would probably break scope. Damn.Scope is not broken. Quite the contrary, it goes on par with its meaning - scope variable can't be null-initialized (it makes no sense at least).
Dec 31 2008
Denis Koroskin:Foo nonNull = new Foo(); Foo? possiblyNull = null;That syntax is now used by various other languages, it's slowly becoming a kind of standard in modern languages that support some form of OOP. Eventually D too will probably grow it (or something close, maybe with another symbol). Bye, bearophile
Dec 31 2008