Consistency, Templates, Constructors, and D3

Era Scarecrow rtcvb32 at yahoo.com
Mon Aug 27 13:22:46 PDT 2012


On Monday, 27 August 2012 at 14:53:57 UTC, F i L wrote:
> 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:

  I'm sure in C# that all structs and classes are heap allocated 
(It takes after C++ very likely) that's the simplest way to do 
it. You can do that in C++ as well, but other than having to 
declare it a pointer first. In C++ they made structs 'classes 
that are public by default' by it's definition I believe. 
Considering how C++ is set up that makes perfect sense.

>     FooType newFoo() {
>         return new FooType( ... );
>     }
>
>     void main() {
>         auto f = newFoo(); // struct or class?
>     }

   By looking at newFoo I'd say a class; But if like in C# I'm 
sure you can't tell the difference (But C++ with the pointer you 
can). And for factory functions I'd put them inside the 
struct/class, unless I had a compelling reason not to.

   class Record {
     static Record newRecord(string options) {
       Record rec = new Record();
       // stuff building the complex record
       return rec;
     }
   }

> 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).

  And a postblits would end up being...? The extra 'this' makes it 
look like an obvious typo or a minor headache.

  this this(this){} //postblitz?

  Honestly I kinda like it how it is now. It's fairly clear and 
concise. Only if you start getting creative can it begin to get 
confusing; Then again in any language someone who decided to make 
it confusing would make it confusing regardless.

--

enum JOJOJO = 100;

class Jo {
   int jojo1;

   Jo jo(Jo JOO) {
     int jojo = 10;
     int joJo = JOJOJO;
     Jo JO = new Jo();
     // and so on and so forth.
   }
}

// Make a new Jo!
Jo newJo(){
   return Jo.jo(null);
}


Jo something = newJo(); //now is this a class or a struct :P 
Right back at you.

--

  Seriously... Actually if you get it confusing enough you could 
submit it to The International Obfuscated C Code Contest. 
http://www.ioccc.org/

  I would say if 'new' is part of the function name, it's returns 
a class. If it's referenced (or a pointer), it could be either. 
But not having a universal constructor would make creating an 
array with defaults impossible without declaring/hinting which 
one to use. It's one reason structs have to have good contents 
for all it's data members at compile-time, so you could create an 
array with defaulted information that works.

  If we take your approach and suggestion, which one should the 
compile assume?

  Something globalSomething;

  class Something {
    this defaultConstructor();
    this duplicate(); //or clone
    this copyGlobalSomething();
    this constructorWithDefault(int x = 100);
  }

  By signature alone... Which one? They are all legal, they are 
uniquely named, and they are all equal candidates. Order of 
functions are irrelevant.


More information about the Digitalmars-d mailing list