| Thread overview | |||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
February 09, 2009 Proposal : allocations made easier with non nullable types. | ||||
|---|---|---|---|---|
| ||||
I think it makes no sense to have nullable pointers in a high level language like D. In D : X x = new X; This is a bit redundant, if we take away the ability to write X x; to mean X x = 0; then we can have X x; mean X x = new X; If the class has a ctor then we can write X x(32); instead of X x = new X(32); Only when the types of the pointer and class are different do we need to write X x = new Y; We can do this syntactically in D because classes cannot be instantiated on the stack (unless scope is used, which I have found a bit pointless, as members are not scope so no deterministic dtor) This makes the code much less verbose and allows code to change from X being a struct to X being a class without having to go around and change all the X x; to X = new X; As I said in the nullable types thread: Passing 0 or 0x012345A or anything else that is not a pointer to an instance of X to a variable declared as X x is the same as mixing in a bicycle when a recipe asks for a cup of olive oil. There are much better, and less error prone ways to write code in a high level language than allowing null pointers. Alex | ||||
February 09, 2009 Re: Proposal : allocations made easier with non nullable types. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Alex Burton | On Mon, 09 Feb 2009 13:48:39 +0300, Alex Burton <alexibu@mac.com> wrote:
> I think it makes no sense to have nullable pointers in a high level language like D.
>
> In D :
>
> X x = new X;
> This is a bit redundant, if we take away the ability to write X x; to mean X x = 0; then we can have X x; mean X x = new X;
> If the class has a ctor then we can write X x(32); instead of X x = new X(32);
> Only when the types of the pointer and class are different do we need to write X x = new Y;
> We can do this syntactically in D because classes cannot be instantiated on the stack (unless scope is used, which I have found a bit pointless, as members are not scope so no deterministic dtor)
>
> This makes the code much less verbose and allows code to change from X being a struct to X being a class without having to go around and change all the X x; to X = new X;
>
> As I said in the nullable types thread:
> Passing 0 or 0x012345A or anything else that is not a pointer to an instance of X to a variable declared as X x is the same as mixing in a bicycle when a recipe asks for a cup of olive oil.
>
> There are much better, and less error prone ways to write code in a high level language than allowing null pointers.
>
> Alex
I remember Andrei has showed interest in unification of the way value and reference types are instantiated:
Foo foo(arg1, arg2); // valid instance, be it reference of value type
Bar bar; // same here (default ctor is called)
and ditch 'new' keyword altogether. Note that you can't delete non-nullable reference so 'delete' keyword is not needed, too (use scope instead). Nullable types, however, may be recycled with e.g. GC.delete(foo);
That said, I'd like to see an experimental version of DMD with these featured enabled. It looks nice at first glance, but time and experience is needed to get better understanding of this.
| |||
February 09, 2009 Re: Proposal : allocations made easier with non nullable types. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Alex Burton | Alex Burton wrote:
> I think it makes no sense to have nullable pointers in a high level language like D.
>
> In D :
>
> X x = new X;
> This is a bit redundant, if we take away the ability to write X x; to mean X x = 0; then we can have X x; mean X x = new X;
> If the class has a ctor then we can write X x(32); instead of X x = new X(32);
> Only when the types of the pointer and class are different do we need to write X x = new Y;
> We can do this syntactically in D because classes cannot be instantiated on the stack (unless scope is used, which I have found a bit pointless, as members are not scope so no deterministic dtor)
>
> This makes the code much less verbose and allows code to change from X being a struct to X being a class without having to go around and change all the X x; to X = new X;
>
> As I said in the nullable types thread:
> Passing 0 or 0x012345A or anything else that is not a pointer to an instance of X to a variable declared as X x is the same as mixing in a bicycle when a recipe asks for a cup of olive oil.
>
> There are much better, and less error prone ways to write code in a high level language than allowing null pointers.
>
> Alex
How would you do this?
X x;
if(someCondition) {
x = new SomeX();
} else {
x = new SomeOtherX();
}
| |||
February 09, 2009 Re: Proposal : allocations made easier with non nullable types. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Ary Borenszweig | On 2009-02-09 06:41:59 -0500, Ary Borenszweig <ary@esperanto.org.ar> said: > How would you do this? > > X x; > > if(someCondition) { > x = new SomeX(); > } else { > x = new SomeOtherX(); > } Well, the declaration could be transformed to this: X x = new X; But since x is not used before being reassigned (for all code paths), the compiler could just leave it uninitialized until you do the assignement yourself. But then perhaps the "new X" should not be elided unless the constructor and and destructor are pure. Another question is what happens when X is an abstract class. -- Michel Fortin michel.fortin@michelf.com http://michelf.com/ | |||
February 09, 2009 Re: Proposal : allocations made easier with non nullable types. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Ary Borenszweig | Ary Borenszweig wrote:
> Alex Burton wrote:
>> I think it makes no sense to have nullable pointers in a high level language like D.
>>
>> In D :
>>
>> X x = new X;
>> This is a bit redundant, if we take away the ability to write X x; to mean X x = 0; then we can have X x; mean X x = new X;
>> If the class has a ctor then we can write X x(32); instead of X x = new X(32);
>> Only when the types of the pointer and class are different do we need to write X x = new Y;
>> We can do this syntactically in D because classes cannot be instantiated on the stack (unless scope is used, which I have found a bit pointless, as members are not scope so no deterministic dtor)
>>
>> This makes the code much less verbose and allows code to change from X being a struct to X being a class without having to go around and change all the X x; to X = new X;
>>
>> As I said in the nullable types thread:
>> Passing 0 or 0x012345A or anything else that is not a pointer to an instance of X to a variable declared as X x is the same as mixing in a bicycle when a recipe asks for a cup of olive oil.
>>
>> There are much better, and less error prone ways to write code in a high level language than allowing null pointers.
>>
>> Alex
>
> How would you do this?
>
> X x;
>
> if(someCondition) {
> x = new SomeX();
> } else {
> x = new SomeOtherX();
> }
That's interesting, because even there, you don't want X to be a nullable type. You don't want x to be readable AT ALL until one of the constructor calls has happened.
In fact, there's already a syntax for this. The solution is:
X x = void;
if(someCondition) {
x = new SomeX();
} else {
x = new SomeOtherX();
}
| |||
February 09, 2009 Re: Proposal : allocations made easier with non nullable types. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Michel Fortin | Michel Fortin wrote: > On 2009-02-09 06:41:59 -0500, Ary Borenszweig <ary@esperanto.org.ar> said: > >> How would you do this? >> >> X x; >> >> if(someCondition) { >> x = new SomeX(); >> } else { >> x = new SomeOtherX(); >> } > > Well, the declaration could be transformed to this: > > X x = new X; > > But since x is not used before being reassigned (for all code paths), the compiler could just leave it uninitialized until you do the assignement yourself. But then perhaps the "new X" should not be elided unless the constructor and and destructor are pure. I don't trust that the compiler would do that. > Another question is what happens when X is an abstract class. Or when X has no default constructor. Or when X's default constructor allocates non-memory resources. Or when X's default constructor depends on global variables that those conditionals set and segfaults or throws when those globals are not in a consistent state. Or when X is a really huge class or does a lot of computation in its constructor and allocating it takes an unreasonable amount of time. Any case in which the default constructor has side effects or preconditions is a problem. | |||
February 09, 2009 Re: Proposal : allocations made easier with non nullable types. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Ary Borenszweig | Ary Borenszweig wrote: > How would you do this? > > X x; > > if(someCondition) { > x = new SomeX(); > } else { > x = new SomeOtherX(); > } One option is the "turn everything into an expression" route. This is what Nemerle (think a functional superset of C#) did, and it's just BEAUTIFULLY expressive. > X x = if( someCondition ) new SomeX(); else new SomeOtherX(); Failing that, there's always this (note: didn't do a syntax check on this :P): > X x = ({if(someCondition) > return new SomeX(); > else return new SomeOtherX();})(); Or something to that effect. -- Daniel | |||
February 09, 2009 Re: Proposal : allocations made easier with non nullable types. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Alex Burton | Alex Burton wrote: > I think it makes no sense to have nullable pointers in a high level language like D. Oh, and how do you intend to make linked lists? Or trees? Or any non-trivial data structure? Saying they have no place in a language is just silly; the question should be whether they should be the default or not (I would contend that they shouldn't be.) > In D : > > X x = new X; > This is a bit redundant, if we take away the ability to write X x; to mean X x = 0; then we can have X x; mean X x = new X; > If the class has a ctor then we can write X x(32); instead of X x = new X(32); Can I just say that I *LOATHE* this syntax? It's one thing I always despised about C++; it simply makes NO sense whatsoever. It looks like the bastard offspring of a function declaration and a function call. The first *is* redundant, but then I wouldn't state X twice, I'd use "auto" (because types are almost never a single letter anyway.) Add to that that the existing syntax is much more intuitive; it even reads like a sentence. > Only when the types of the pointer and class are different do we need to write X x = new Y; > We can do this syntactically in D because classes cannot be instantiated on the stack (unless scope is used, which I have found a bit pointless, as members are not scope so no deterministic dtor) I made a proposal quite some time ago detailing how we could have not only scope members of classes, but even scope RETURN values, but I think it got maybe one reply... :P Given that one of D's tenets is to make it simpler to write deterministic, bullet-proof code, the complete lack of deterministic destruction of classes has always felt like a huge hole in the language. > This makes the code much less verbose and allows code to change from X being a struct to X being a class without having to go around and change all the X x; to X = new X; Something interesting about C# that I'd forgotten until recently... > Vector2 v = new Vector2(); What is Vector2? ... It's a struct. In C#, there's no syntactic difference between instantiating a class and initialising a struct. Most C# code doesn't have pointers, so this isn't an issue. (Note that I don't have any idea how you would heap-allocate a value type in C#; I'm not even sure if it's possible...) > As I said in the nullable types thread: > Passing 0 or 0x012345A or anything else that is not a pointer to an instance of X to a variable declared as X x is the same as mixing in a bicycle when a recipe asks for a cup of olive oil. Passing garbage to a function doesn't have any bearing on the non-nullable discussion. If you're casting random integers to pointers and passing them to functions, you reap what you sow. :) That said, passing null is more like omitting an ingredient. Which is unfortunate if you're making soup and the ingredient is "water." > There are much better, and less error prone ways to write code in a high level language than allowing null pointers. > > Alex While I'm a strong believer in non-nullable types, I don't think null pointers are evil. They're a tool like anything else; problems only arise when you misue them. I believe they're the wrong default choice, because they don't come up in normal code, but you've got to fall over yourself to make sure they don't become an issue. Let me chip in a practical example that happened just yesterday. I'm throwing together a game prototype. Since this is C#, I don't have contracts, so I'm making judicious use of Debug.Assert calls to ensure that object references are non-null. And surprise, surprise, my program crashes with null dereference errors. I walk the stack trace back, only to discover that the null got stored at some point. So the program doesn't even crash when the problem occurs (storing a null reference in a field that shouldn't have one) it occurs later in the execution when I'm no longer able to easily determine what went wrong. Eventually, I tracked it down to one of the few places in the code that I forgot to assert the reference was non-null. It was null because Microsoft didn't bother to document that a particular "magic object" doesn't exist until a certain point. -- Daniel | |||
February 09, 2009 Re: Proposal : allocations made easier with non nullable types. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Alex Burton | Alex Burton wrote: > I think it makes no sense to have nullable pointers in a high level language like D. > > In D : > > X x = new X; > This is a bit redundant, if we take away the ability to write X x; to mean X x = 0; then we can have X x; mean X x = new X; > If the class has a ctor then we can write X x(32); instead of X x = new X(32); > Only when the types of the pointer and class are different do we need to write X x = new Y; Add this code to your class X: static X opCall(T...)(T x) { return new X(x); } Then you can write: > auto x = X(); Can it get any less redundant? The opCall is a bit annoying, but needs to be written only once. > We can do this syntactically in D because classes cannot be instantiated on the stack (unless scope is used, which I have found a bit pointless, as members are not scope so no deterministic dtor) > > This makes the code much less verbose and allows code to change from X being a struct to X being a class without having to go around and change all the X x; to X = new X; For structs, use opCall() to initialize them. opCall is the best way to initialize a struct, because struct literal are totally utterly useless. If you use opCall to initialize classes as well (see above), then the syntax for initializing structs and classes will be exactly the same. > As I said in the nullable types thread: > Passing 0 or 0x012345A or anything else that is not a pointer to an instance of X to a variable declared as X x is the same as mixing in a bicycle when a recipe asks for a cup of olive oil. > > There are much better, and less error prone ways to write code in a high level language than allowing null pointers. Like what? > Alex | |||
February 09, 2009 Re: Proposal : allocations made easier with non nullable types. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Daniel Keep | Daniel Keep wrote:
> One option is the "turn everything into an expression" route. This is
> what Nemerle (think a functional superset of C#) did, and it's just
> BEAUTIFULLY expressive.
>
>> X x = if( someCondition ) new SomeX(); else new SomeOtherX();
>
> Failing that, there's always this (note: didn't do a syntax check on
> this :P):
>
>> X x = ({if(someCondition)
>> return new SomeX();
>> else return new SomeOtherX();})();
>
> Or something to that effect.
Like this?
X x = (someCondition) ? new SomeX() : new SomeOtherX();
*Much* preferred to delegate trickery, I'd think...
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply