Pluggable type sytems

Bartosz Milewski bartosz at relisoft.com
Sun Feb 8 17:09:26 PST 2009


I just assume that any extension of the already complex D type system will be met with a lot of resistance. I remember the all-out wars about const and immutable (a.k.a invariant). Even those extensions are still half-assed: the construction of immutable objects and const polymorphism issues remain. 

My impression is that theoreticians and very advanced programmers love elaborate type systems. Nine-to-five programmers, which are in the majority, prefer simplicity even if the cost is reliability. Just look at the comments to my blog post. 

I know we have to do something about null references in D, but I'm still on the fence about how we should accomplish that.

Denis Koroskin Wrote:

> On Mon, 09 Feb 2009 01:19:55 +0300, Bartosz Milewski <bartosz at relisoft.com> wrote:
> 
> > I also believe that non-null should be the default. Most references in a  
> > typical program are assumed to be non-null.
> >
> 
> Oh, that's true!
> 
> > Like for every default, there should be an escape mechanism from it.  
> > However, adding "nullable" to the type system might be controversial,  
> > especially because it requires special treatment of constructors and  
> > polymorphism (hence additional type modifiers, raw and poly-null, and I  
> > haven't even mentioned wildcard annotations).
> >
> 
> Common opinion is that this is worth the trouble these days. More and more people discuss, write articles on non-nullable types and incorporate them into languages. Main C# architects has stated that absence of non-nullable types by default is his greatest mistake that is too late to be fixed.
> 
> > So some time ago I came up with a more modest proposal. The compiler  
> > should catch nullable references at their source. It should enforce what  
> > I call "declaration is initialization" (DII). For instance, the  
> > following is correct:
> >
> > Foo foo = new Foo;
> >
> > and the following is not:
> >
> > Foo foo; // error
> > ...
> > foo = new Foo;
> >
> > Obviously this rule is too strict, so there must be a way to override  
> > it. Here's the simple syntax:
> >
> > Foo foo = null; // not an error!
> >
> 
> And what about value types? Why special treatment for reference types only? I don't like rules like that in a language:
> 
> Foo foo; // error
> int i; // okay?
> 
> If not, and this is an error, too, then this defeats the whole purpose of having T.init in D, because it will never be used per your proposal:
> 
> int i = 0; // initialized explicitly
> char c = char.init; // would you use that?
> 
> > Notice that the programmer explicitly states that one should be careful  
> > when using foo, because it might be null.
> >
> > Since this solution doesn't involve the type system, the nullability  
> > doesn't propagate across function calls. But it might be a tradeoff  
> > worth taking, if only for the simplicity.
> >
> 
> Naah.. The whole purpose of having non-nullable types is that given a pointer you are sure it is not null:
> 
> string toString(Object o)
> {
>    // is it null or not? Should I check for null or not? What if it is null?
>    // Should I throw? What kind of exception?
>    // But was going to make it nothrow! So what, no checks?
>    // Just fail with access violation? Is this the best D can do?
> 
>    return o.toString();
> }
> 
> As an end user, you neglect and avoid null checks in your code ("I'm sure I won't pass null here"). And then you run your program half an hour, it segfaults with access violation and you don't have any clue where did null dereference take place. I have came across this situation so many times that I hate it.
> 
> As a library designer, you end up having null checks everywhere in your code which is some kind of a paranoia because in 99% of cases the pointer will be not null. But why put so many special case and checks if it is *disallowed* to run code with null pointer in first place? So people decided - let's enforce that at compile time! That's the whole point of the feature - disallow invalid use cases at compile time. You get cleaner code (no unnecessary null-checks and throws) and small performance improvement as a bonus.
> 
> I would like to write code as this as be sure that it will never fail:
> 
> string toString(Object o) // non-nullability is enforced at compile time
> {
>     return o.toString();
> }
> 
> This is D style - do as much as possible at compile time - and I believe non-nullable types fit D type system very well.
> 
> > Constructors still need some special treatment. Every class member  
> > variable must be initialized in the constructor. Again, the escape is to  
> > _explicitly_ initialize it to null. This might seem redundant, since the  
> > variable is already default initialized to null, but the compiler can  
> > easily eliminate such redundancies.
> >
> > I also found out that Java's editor, Eclipse, enforces DII--a very  
> > useful feature that paid off for me in the first 100 lines of code I  
> > wrote after a long period of inactivity in Java ;-)
> >
> >> Michel Fortin Wrote:
> >
> >> In fact, I'd even argue that non-nullability should be the default for
> >> pointers and class references, because it is either safer (if the
> >> compiler doesn't do the null check for you) or less troublesome to use
> >> (if the compiler forces you to check for null everytime). Another
> >> reason being consistency: value-types can't be null by default and so
> >> should be class references and pointers. And making pointers
> >> non-nullable by default can only be done at the language level, so
> >> obviously it's better in the language than as a user-defined type
> >> modifier.
> >
> 
> 




More information about the Digitalmars-d mailing list