Consistency, Templates, Constructors, and D3

F i L witte2008 at gmail.com
Mon Aug 27 07:53:55 PDT 2012


Era Scarecrow wrote:
>  Except being somewhat unfamiliar with it, I can only look it 
> over and go 'huh? what's going on?'.
>
>  new being a keyword from C++ for allocate on the heap 
> immediately makes this whole thing confusing. I would wonder 
> myself: Is this on the stack or in the heap for the whole 
> thing? Is Point a struct or a class? Then I wonder assuming 
> that you get 5 for the length, then would all the elements be 
> set the same or just the first one?

in C#, you use 'new Type()' for both classes and structs, and it 
works fine. In fact, it has some benefit with generic 
programming. Plus, it's impossible to completely get away from 
having to understand the type, even in C++/D today, because we 
can always make factory functions:

     FooType newFoo() {
         return new FooType( ... );
     }

     void main() {
         auto f = newFoo(); // struct or class?
     }

However, I do agree it would be nice having some kind of 
distinction between stack/heap allocation and copy/ref semantics. 
Because constructor names are completely arbitrary in my 
proposal, I think you could easily just choose a different name 
(say, 'new' vs 'set').

     struct Foo {
         this set() { ... }
     }

     class Bar {
         this new() { ... }
     }

     void main() {
         auto f = Foo.set( ... ); // stack/copy
         auto b = Bar.new( ... ); // heap/ref
     }

Again, this is just an arbitrary distinction and wouldn't be 
enforced, so third-party libs could choose something completely 
different... but then, they always could (like above) so it's 
benefit is debatable.

I've had ideas before about having two different '=' operators 
for assignment and copy, but honestly, I think just looking up 
and understanding the types you're working with might be the best 
solution. A task much easier with proper IDE tooltips and the 
like.


>  Would new still be a key word?

No. You could just as easily name your constructor 
'freshCopyYo()'. In fact, you often want multiple constructor 
names for different constructing procedures, like I explain in my 
original post. For instance if you're loading from a file, having 
a 'load()' constructor makes more sense than 'new()'. When 
converting from some other type, have a 'from()' constructor. The 
name implies the action, but they all "construct" the type:

     class Text
     {
         this new()         // blank
         this new(string s) // basic constructor

         this from(int i)   // convert from int
         this from(float f) // convert from float

         this load(string filename) // load from file
     }

All of these are constructors, because they're return type is 
'this'. They all implicitly allocate an object and have a 'this' 
reference. However, their names and implementations are 
completely arbitrary, which is a good thing because we need and 
use these arbitrary constructors all the time today, we just have 
to do it in a completely inconsistent way (static factory 
functions).


> If not (and uses a regular function signature as you propose), 
> then what if someone decided to use new for something other 
> than allocation and returned something other than the type you 
> were expecting from the view above? (Say, making a 2d matrix?)

You can ask the same question about any functions today (see the 
first code example of this post). It's possible to make a 
function 'add' that actually subtracts, but realistically no one 
is going to do it.

Free Lists (memory pooled objects) are a perfect example of when 
you want a constructor that doesn't [always] allocate memory, and 
I describe this example in my original post.

Also, there are times when you actually want to return a 
different (but often related) type. Dart has special "constructor 
factories", which overrides 'new Type()' syntax, that's built for 
just that 
(http://www.dartlang.org/articles/idiomatic-dart/#constructors 
scroll down a little to 'factory constructors').

With my proposal, a function which returns type 'this' would 
always return that type, but because they're invoked like any 
other static function, you can easily define a static factory 
function which "appears" to be a constructor (based on it's name).


More information about the Digitalmars-d mailing list