February 11, 2005
> Why does it matter whether it's a constructor or a free function, both are  returning an Airplane.

Because it's really different if you get a new instance or an old instance. If you see new, you know it's a new instance, if you don't see it, you don't know what you'll get unless you go look it up..


> It also means that if the programmer intends not to construct something  they actually have to say so. 

You would trade implicitly doing nothing to implicitly constructing an object. Which is more obvious?


> So, as the OP mentions you can't forget to  construct it, you can only 
> forget not to, meaning you trade a possible  runtime crash (or
> compile time error) for a potentially negligible  performance hit.

Just because something is null, it doesn't mean that a default object will be better, it can easily be much worse.. Usually, when an error occurs (such as a null reference when it shouldn't be), it's best to stop, not to continue in some undefined way.. Consider this:

class Selection
{
    this()
    {
        // initialize to everything
    }

    void filter(..)
    {
        // select some things
    }
}

class DeleteOp
{
    Selection selection;

    void setSelection(Selection newSelection)
    {
        this.selection=newSelection;
    }

    void doDelete()
    {
        // delete all things in selection
    }
}


Now, if you forget to setSelection(), wouldn't you prefer a runtime error than to have everything deleted?


xs0
February 11, 2005


Charlie Patterson wrote:
> I've always wondered about the requirement of the word new in Java.  It appears Java (I don't know much about it) pretends there are no references/pointers to help the poor coder who can't handle it (so I've read as the reason):

Actually in Java ALL objects are referenced by a 'pointer' (called a reference, which is in effect a safe pointer).  Personally I think true pointers are a wonderful source of bugs and should be consigned to OS and device driver development.

> 
>    Airplane A = new Airplane();
>    // work with A
> 
>    // Make a new Airplane for the following function
>    Fly( new Airplane( bar, 3 ) );
> 
>     Airplane B;
>     // dont' work with B yet or a run-time error occurs

I would argue that allocation of memory should be in big neon letters, since that is usually the slower parts of most imperative languages. Simplicity is a goal of D.

C++ has gone overboard here:(from http://nothings.org/computer/cpp.html)

[quote]
In C++ there are eight syntaces and quite a few semantics.

No joke:

   1. regular function call (expression context): foo(a,b)
   2. constructor call (declaration context): Foo foo
   3. constructor call (declaration context): Foo foo(a,b)
   4. constructor call (expression context): new Foo
   5. constructor call (expression context): new Foo(a,b)
   6. destructor call (block end): }
   7. destructor call (statement context): delete foo;
   8. overloaded operator (expression context): foo+bar

(I'll fold copy/assignment constructors in with overloaded operators.)
[/quote]

I would say cleaning up those issues is a _good_ thing.  If you want stack allocation use structs, heap allocation use classes. Its very straightforward.

It doesnt save THAT much typing and the readability is much better.
February 11, 2005
>Well, for one thing, Airplane() could be a function or method; if there's a new in front of it, you immediately know that it's a class. (and code obviousness is rather important, if you ask me; quite a lot of projects are worked on by more than one person...).

Oh, those poor C++-Programmers.
In C++ you create objects without new, if you want them to be on the stack. In
ML-like languages you call constructors without new, too. And nobody is
confused.


>Plus, in many cases you don't want an object immediately, but at some point in the future (think lazy initialization). How would you handle that?

Right, I don't like th original proposal, too.
I'd vote for
#   Airplain foo;
stays as is.

But we still don't need 'new':
Airplain foo = Airplain();


-- Matthias Becker


February 11, 2005
>I've always wondered about the requirement of the word new in Java.  It appears Java (I don't know much about it) pretends there are no references/pointers to help the poor coder who can't handle it (so I've read as the reason):
>
>   Airplane A = new Airplane();
>   // work with A
>
>   // Make a new Airplane for the following function
>   Fly( new Airplane( bar, 3 ) );
>
>    Airplane B;
>    // dont' work with B yet or a run-time error occurs
>
>So, with such an emphasis on "no pointers" and coddling the pre-school coder, why the use of the word new?  It feels very pointer'ish to me. Forgetting it would cause a strange thing called a bad reference.  Scary! Why not
>
>   Airplane A;
>   // use default airplane

Why? Why isn't that a null-Reference? I'd prefer
#   Airplane A = Airplane();


>   Airplane A = Airplane( 3 );
>   // use specially constructed airplane
>   // could have also just been a regular function like A = Init( 3 );
>
>   // Make a new Airplane for the following function
>   Fly( Airplane( bar, 3 ) );
>
>This "new" practice has been copied to javascript, php, and now D.  Why? And before you hit me up with an efficiency issue, well OK, but these languages aren't bastions of efficiency and so why leave a possible run-time error hanging?
>
>


February 11, 2005
>Because, imho, constructors do things and moreover sometimes don't exist.  Your example would only not compile if Airplane had no constructor that took zero arguments.  Consider this code:
>
>Airplane A;
>try
>    A = airport.getAirplane(AIRPLANE_FLYING);
>catch (AirplaneHasCrashedException)
>    A = airport.getAirplane(AIRPLANE_GROUND);
>
>Okay, a dumb example I'm sure, but I think it illustrates the point.  I would be REQUIRED to add a dummy constructor, and a PUBLIC dummy constructor no less, to the Airplane class for that code to work under your example.

Nope.

#  Airplane A = null;
#  try
#      A = airport.getAirplane(AIRPLANE_FLYING);
#  catch (AirplaneHasCrashedException)
#      A = airport.getAirplane(AIRPLANE_GROUND);


-- Matthias Becker


February 11, 2005
> Actually in Java ALL objects are referenced by a 'pointer' (called a reference, which is in effect a safe pointer).  Personally I think true pointers are a wonderful source of bugs and should be consigned to OS and device driver development.

While we're on that subject, why let OS guys do it either?

> I would argue that allocation of memory should be in big neon letters, since that is usually the slower parts of most imperative languages. Simplicity is a goal of D.

I would think the "simpler" thing would be to have less keywords and syntax. But again, I'm mostly asking out of curiosity, not to change D.  I just wonder about the original of some quirks I've never understood.

> C++ has gone overboard here:(from http://nothings.org/computer/cpp.html)
>
> [quote]
> In C++ there are eight syntaces and quite a few semantics.
>
> No joke:
>
>    1. regular function call (expression context): foo(a,b)
>    2. constructor call (declaration context): Foo foo
>    3. constructor call (declaration context): Foo foo(a,b)
>    4. constructor call (expression context): new Foo
>    5. constructor call (expression context): new Foo(a,b)
>    6. destructor call (block end): }
>    7. destructor call (statement context): delete foo;
>    8. overloaded operator (expression context): foo+bar
>
> (I'll fold copy/assignment constructors in with overloaded operators.)
> [/quote]

I think C++ is complicated but I think that list isn't really fair.  It basically has two orthogonal issues: building on the stack vs heap (new or not new) and listing parameters, which can be done without the () if there are none.  Two basic rules, not 8 "syntaxes."

Further, if D has just one syntax, then why add the word "new".  Any constuctor will use the heap and doesn't need the memory deleted manually. So why use a keyword that drums up visions of stack vs heap debates and manual memory allocation?


February 11, 2005
"xs0" <xs0@xs0.com> wrote in message news:cui9fv$1sr0$1@digitaldaemon.com...
>> Yeah, I guess you'd have to have a rule that you can't name a function the same as an object name.
>
> Still, AFAIK, that would break the context-freeness of D's grammar, which Walter stated as one of the design goals of the language.

I don't know about this assumption, but still I don't see how this breaks context-free.  If a function returns an Airplane, it is a syntax error to assign it to anything but an Airplane (or base class).  Nothing new.

>> Then again, if I wanted to initialize a class with some non-member function, why couldn't I?  Or you could take the tact that I believe D does and
> > have
>>
>>     Airplane A = this( 3 );
>>     Airplane B;
>>
>>    b = this();
>
> That's even worse. this primarily refers to the object instance in a method (i.e. void setX(double x) { this.x=x; }), not to the constructor..

I'm new to reading about D, but I don't think I started it.  Doesn't D use this() and ~this() for construction and destruction?  Sure it doesn't require the coder using these words to actually create an instance, but they are used as function names nonetheless.

>> As for your second point, about lazy initialization: I don't see why garbage collected languages care that much.  It seems ease of understanding and coding take the front seat and efficiency loss can be tolerated.

> What does lazy initialization have to do with languages? It's just a common programming technique. Anyhow, consider for example a cache or pool of something; how would you initialize it non-lazily?

Some languages are inefficient for some problem domains because they allocate memory early and often.  The member initialization feature for C++ is designed to remove any unnecessary construction:

    class Airplane
    {
        string pilot;
        ...
    };

    Airplane::Airplane ( )
    {
        pilot = "none";
    }

By the time pilot is set to "none" in the constructor, a default string was already created, and now it is being reassigned, all with the heap (= expensive) memory.  Instead do:

    Airplane::Airplane ( )
    : pilot( "non" )
    {
    }

Not beautiful, but it is super efficient and avoids any non-lazy initialization.  Conversely, a language that is going for simplicity (over a little performance) could avoid the C++ trick AND the run-time null object problem by initializing every object, even "Airplane A;" with some default. After all, ints, bits and every other built-in type have to have *some* value.  Why shouldn't *all* objects have some value instead of putting them in between.  This confuses me about the ideology of these languages.  Why try to remove pointers because they are buggy, but then leave a freakin' pointer for objects?  Make an object feel substantial, just like an int.

I guess the creators of these languages feel it is too big of an efficiency hit, because, again I don't see why they should rail against pointers and then leave the biggest of all dangling like that.

As for initializing a cache or pool or something, make an empty pool instead of a null pointer to a non-pool.  The user can immediately re-instantiate it with a better one, at a small cost in time.

>> A smarter compiler could wait to use a default constructor when the object it first used, perhaps?
>>
>>     Airplane A; // no constructor; saves time
>>
>>     A.rotor = ROTOR_PROP; // first use, sneak in a default constructor.
>
> What if it's constructed somewhere else? And usually, if a null is accessed, it's an error that should not be ignored by constructing the object (btw, this would also mean that practically every object access would need the null check)..

Alternatively objects could become slightly heavier and, instead of being a simple pointer to memory, they could be a pointer and an init flag... Again, more costly but it bring the ideology of objects as first class entities to fruition.  Currently I can create ints and use them, but I can't just create an Airplane and start using it == not first class.

    int i;
    i = 0;  // of course, you have made an int;
    Airplane A;
    A.rotor = ROTOR_PROPR; // oops!  you didn't really make an airplane


February 11, 2005
In article <cuinrp$2cva$1@digitaldaemon.com>, Matthias Becker says...
>
>Right, I don't like th original proposal, too.
>I'd vote for
>#   Airplain foo;
>stays as is.
>
>But we still don't need 'new':
>Airplain foo = Airplain();

This breaks opCall. (And you can get the effect you want already by writing your
own opCall.)

How about just:

Airplane foo(10);   equivalent to    Airplane foo = new Airplane(10);
Airplane foo();     equivalent to    Airplane foo = new Airplane;
Airplane foo;       same as now

This eliminates many cases of 'new' without breaking a single line of existing code. I'm surprised nobody have suggested this yet. (Or if they have I have just missed it :-)

Nick


February 11, 2005
> I don't know about this assumption, but still I don't see how this breaks context-free.  If a function returns an Airplane, it is a syntax error to assign it to anything but an Airplane (or base class).  Nothing new.

perform(task(...))

is task a class or a function?


> I'm new to reading about D, but I don't think I started it.  Doesn't D use this() and ~this() for construction and destruction?  Sure it doesn't require the coder using these words to actually create an instance, but they are used as function names nonetheless.

Sure, but "this" has a different meaning except in the specific context of being used as a method name within a class..


> Not beautiful, but it is super efficient and avoids any non-lazy initialization.  Conversely, a language that is going for simplicity (over a little performance) could avoid the C++ trick AND the run-time null object problem by initializing every object, even "Airplane A;" with some default. 

But you need null at least sometimes (see other posts). If you do have nulls, you can't completely avoid the run-time null object problem. And like I already stated in another post, having null and crashing can be much better than having a default object instead of the null and not crashing.


> After all, ints, bits and every other built-in type have to have *some* value.  Why shouldn't *all* objects have some value instead of putting them in between.  This confuses me about the ideology of these languages.  Why try to remove pointers because they are buggy, but then leave a freakin' pointer for objects?  Make an object feel substantial, just like an int.

Well, it does somewhat suck that primitive types are treated differently than structs and again differently than classes. But each serves their own purpose, so why would you take that away? A good-for-everything is great-for-nothing.


> I guess the creators of these languages feel it is too big of an efficiency hit, because, again I don't see why they should rail against pointers and then leave the biggest of all dangling like that.

Pointers aren't all bad, it's just what you can do in C with them that's bad :) And it's not pointers that are buggy, it's programmers :)


> As for initializing a cache or pool or something, make an empty pool instead of a null pointer to a non-pool.  The user can immediately re-instantiate it with a better one, at a small cost in time.

Ahh, but how do I make the empty pool (or a half-filled pool for that matter)? Should I reallocate arrays and copy contents of the pool's vars on each and every addition/removal? Isn't that more error-prone than handling nulls?


> Alternatively objects could become slightly heavier and, instead of being a simple pointer to memory, they could be a pointer and an init flag... Again, more costly but it bring the ideology of objects as first class entities to fruition.  Currently I can create ints and use them, but I can't just create an Airplane and start using it == not first class.
> 
>     int i;
>     i = 0;  // of course, you have made an int;
>     Airplane A;
>     A.rotor = ROTOR_PROPR; // oops!  you didn't really make an airplane

Sure you can:

Airplane A;
A=null;
A=someOtherAirplane;


You just didn't make A.rotor :) But seriously, it's exactly like saying doubles should never have the NaN value, even though NaNs are extremely useful in some contexts, although they behave almost like nulls (i.e. they fail your arithmetics and/or comparisons; heck, they're even not equal to themselves).

And AFAIK, dividing an integer by zero will cause exceptions on most systems, would you eliminate that as well? What should happen in that case? Isn't that a source of crashes? Would you then forbid the value 0 of ever being stored in memory?


xs0
February 11, 2005
> Oh, those poor C++-Programmers.
> In C++ you create objects without new, if you want them to be on the stack. In
> ML-like languages you call constructors without new, too. And nobody is
> confused.

I'm not a C++ programmer :P And who says nobody is confused? What is a stack anyway? (I know it, but many people don't; I also know that the right amount of verbosity is certainly better than too little or too much; new as-is to me feels just right)



> But we still don't need 'new':
> Airplain foo = Airplain();

well, that seems OK, but how about

Airplane foo = Fighter(); // function/class?

or even

Task(...).process();

is that a new task, or something looked up? if you have new, there's no ambiguity there..



xs0