www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - class instance construction

reply spir <denis.spir gmail.com> writes:
Hello,


First, what is the actual point of "new"? I find this keyword rather helpfu=
l in that it reminds me the element is referenced/heap-allocated/GC'ed. But=
 is there any ambiguity on the language's side? We cannot construct a class=
 instance in any other way, AFAIK, and "calling" a class can hardly have an=
y other sense. Maybe classes' opCall could be set to the creation routine (=
whatever new calls); then we would get a single object-creation syntax.
This is no request :-) I just ask to try & understand the rationale behind =
"new".

Note that this pattern is also a kind of literal notation for anonymous obj=
ects, which leads to rather obfuscated expression of the form:
	c =3D new C(new C1(p1), new C2(p2)), new C3(p3));

Still, an other case when "new" annoys me is method chaining, because it ma=
kes syntax heavier and less readable:
	c =3D (new C(p)).do(x);
versus:
	c =3D C(p).do(x);
Or, maybe, the parser could be clever enough to correctly decode:
	c =3D new C(p).do(x);



Second, could there be a default constructor for classes, like for structs?=
 Namely, one that sets declared fields:
	class C {int i;}
	...
	auto c =3D new C(1);
This is one great advantage of static languages, that the compiler knows mo=
re thank to declarations. Isn't it sensible to use this knowledge when help=
ful? I simply find the following stupid (I mean it's job for a machine, not=
 for a programmer):
	class C {
	    int i;
	    this (int i) {this.i =3D i;}
	}
As we already enjoy this feature for structs...


Denis
-- -- -- -- -- -- --
vit esse estrany =E2=98=A3

spir.wikidot.com
Nov 11 2010
next sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
spir <denis.spir gmail.com> wrote:

 First, what is the actual point of "new"?

Mostly, it's a remnant from C++.
 I find this keyword rather helpful in that it reminds me the element is  
 referenced/heap-allocated/GC'ed. But is there any ambiguity on the  
 language's side? We cannot construct a class instance in any other way,  
 AFAIK, and "calling" a class can hardly have any other sense. Maybe  
 classes' opCall could be set to the creation routine (whatever new  
 calls); then we would get a single object-creation syntax.

Indeed it could. I believe Andrei Alexandrescu has discussed in favor of such a change in the past.
 Still, an other case when "new" annoys me is method chaining, because it  
 makes syntax heavier and less readable:
 	c = (new C(p)).do(x);
 versus:
 	c = C(p).do(x);
 Or, maybe, the parser could be clever enough to correctly decode:
 	c = new C(p).do(x);

One would think it possible to stop searching right upon first finding a function call parentheses (as opposed to a template parentheses). This is complicated by the allowance of the syntax 'new C;'.
 Second, could there be a default constructor for classes, like for  
 structs? Namely, one that sets declared fields:
 	class C {int i;}
 	...
 	auto c = new C(1);

There could. :p As for whether there should, I'm not sure. I would say such a constructor should disappear, should the class designer add other constructors. That, coupled with classes usually being more complex than that (mine are, at least), this seems like a feature that would have little actual air-time.
 This is one great advantage of static languages, that the compiler knows  
 more thank to declarations. Isn't it sensible to use this knowledge when  
 helpful? I simply find the following stupid (I mean it's job for a  
 machine, not for a programmer):
 	class C {
 	    int i;
 	    this (int i) {this.i = i;}
 	}
 As we already enjoy this feature for structs...

The syntax this( int this.i ) {} has been suggested for automatic initialization of fields. I like this suggestion, but it is unlikely to find its way into the language any time soon. -- Simen
Nov 11 2010
prev sibling next sibling parent Justin Johansson <no spam.com> writes:
On 11/11/10 20:02, spir wrote:
 Hello,


 First, what is the actual point of "new"? I find this keyword rather helpful
in that it reminds me the element is referenced/heap-allocated/GC'ed. But is
there any ambiguity on the language's side? We cannot construct a class
instance in any other way, AFAIK, and "calling" a class can hardly have any
other sense. Maybe classes' opCall could be set to the creation routine
(whatever new calls); then we would get a single object-creation syntax.
 This is no request :-) I just ask to try&  understand the rationale behind
"new".

As far as I can make out, though likely I am wrong, there is no need for "new" in a "pure" garbage-collected language, that is, wherein there is no corresponding "delete". Perhaps "new" in a "by-default-GC-collected-PL" should signal that the newly allocated object is not subject to automatic GC and that a corresponding "delete" should ensure to (1) avoid miscapture by GC and (2) to provide backward compatibility for C++ semantics. To use dotNet parlance, perhaps "new" and "delete" should only apply in the context of "unmanged objects". Really I don't know enough about the subject to make a call on this, though I suspect if you push the point enough there will be a torrent of discussion and opposing views on the subject. I do agree though that this topic deserves a first-class discussion. Best wishes, Justin Johansson
Nov 11 2010
prev sibling next sibling parent reply Daniel Gibson <metalcaedes gmail.com> writes:
spir schrieb:
 Still, an other case when "new" annoys me is method chaining, because it makes
syntax heavier and less readable:
 	c = (new C(p)).do(x);
 versus:
 	c = C(p).do(x);
 Or, maybe, the parser could be clever enough to correctly decode:
 	c = new C(p).do(x);
 

Is this really a common case? Constructing an object, just to call *one* method on it and then throw it away?
 
 Second, could there be a default constructor for classes, like for structs?
Namely, one that sets declared fields:
 	class C {int i;}
 	...
 	auto c = new C(1);
 This is one great advantage of static languages, that the compiler knows more
thank to declarations. Isn't it sensible to use this knowledge when helpful? I
simply find the following stupid (I mean it's job for a machine, not for a
programmer):
 	class C {
 	    int i;
 	    this (int i) {this.i = i;}
 	}
 As we already enjoy this feature for structs...
 

Again: Is that a common case? A constructor (probably with multiple arguments) that all just set the corresponding fields of the object? However, I agree that all that this.i = i; is tedious. As I have suggested before in another thread (and Simen did in this thread), something like this( int this.i, float this.y, Foo f) { // f is no field of the class. this.b = new Bar(f, i); } would be helpful because you could mix arguments that are just passed with arguments you want to use in the constructor without too much writing overhead. Cheers, - Daniel
Nov 11 2010
parent Daniel Gibson <metalcaedes gmail.com> writes:
Steven Schveighoffer schrieb:
 On Thu, 11 Nov 2010 12:10:42 -0500, Steven Schveighoffer 
 <schveiguy yahoo.com> wrote:
 
 On Thu, 11 Nov 2010 11:57:40 -0500, Daniel Gibson 
 <metalcaedes gmail.com> wrote:

 spir schrieb:
 Still, an other case when "new" annoys me is method chaining, 
 because it makes syntax heavier and less readable:
     c = (new C(p)).do(x);
 versus:
     c = C(p).do(x);
 Or, maybe, the parser could be clever enough to correctly decode:
     c = new C(p).do(x);

Is this really a common case? Constructing an object, just to call *one* method on it and then throw it away?

If the do method returns this, you aren't throwing it away.


Ok, this is a case I didn't think of, you're right :-)
 
 A realistic example (from dcollections):
 
 auto ll = (new LinkedList(someOtherCollection)).sort();
 
 http://www.dsource.org/projects/dcollections/browser/branches/d2/dcollecti
ns/LinkList.d#L1054 
 
 
 That being said, I'm really ambivalent on whether this needs to be 
 included.  It's not that terrible that you have to parenthesize properly.

Also, I'm not sure if this is a common case.. although I had similar situations as well (it was more like (new Cursor(somecollection)).where(...).select(..) with where() and select() returning a Cursor that wrapped/used the preceding cursor.. and also it was Java). But I don't know if this is useful for other kinds of code that don't deal with collections or similar stuff.
 
 -Steve

Cheers, - Daniel
Nov 11 2010
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 11 Nov 2010 11:57:40 -0500, Daniel Gibson <metalcaedes gmail.com>  
wrote:

 spir schrieb:
 Still, an other case when "new" annoys me is method chaining, because  
 it makes syntax heavier and less readable:
 	c = (new C(p)).do(x);
 versus:
 	c = C(p).do(x);
 Or, maybe, the parser could be clever enough to correctly decode:
 	c = new C(p).do(x);

Is this really a common case? Constructing an object, just to call *one* method on it and then throw it away?

If the do method returns this, you aren't throwing it away. -Steve
Nov 11 2010
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 11 Nov 2010 12:10:42 -0500, Steven Schveighoffer  
<schveiguy yahoo.com> wrote:

 On Thu, 11 Nov 2010 11:57:40 -0500, Daniel Gibson  
 <metalcaedes gmail.com> wrote:

 spir schrieb:
 Still, an other case when "new" annoys me is method chaining, because  
 it makes syntax heavier and less readable:
 	c = (new C(p)).do(x);
 versus:
 	c = C(p).do(x);
 Or, maybe, the parser could be clever enough to correctly decode:
 	c = new C(p).do(x);

Is this really a common case? Constructing an object, just to call *one* method on it and then throw it away?

If the do method returns this, you aren't throwing it away.

A realistic example (from dcollections): auto ll = (new LinkedList(someOtherCollection)).sort(); http://www.dsource.org/projects/dcollections/browser/branches/d2/dcollections/LinkList.d#L1054 That being said, I'm really ambivalent on whether this needs to be included. It's not that terrible that you have to parenthesize properly. -Steve
Nov 11 2010
prev sibling next sibling parent spir <denis.spir gmail.com> writes:
On Thu, 11 Nov 2010 17:57:40 +0100
Daniel Gibson <metalcaedes gmail.com> wrote:

 spir schrieb:
 Still, an other case when "new" annoys me is method chaining, because i=


 	c =3D (new C(p)).do(x);
 versus:
 	c =3D C(p).do(x);
 Or, maybe, the parser could be clever enough to correctly decode:
 	c =3D new C(p).do(x);
=20

Is this really a common case? Constructing an object, just to call *one* method on it and then throw it=

:-) It does not throw it away, instead returns this. And yes, this is commo= n practice. For instance in a PEG matching lib, I want to be able to set ma= tch actions to pattern, like: realNumber =3D new Tuple(digits, DOT, digits).setAction(toFloat); Or even (by overriding opCall): realNumber =3D new Tuple(digits, DOT, digits)(toFloat); Very practical: it lets one define the pattern in one go w/o sacrigficing r= eadability (well, at least in wy views -- but sure it's dicussable).
 Second, could there be a default constructor for classes, like for stru=


 	class C {int i;}
 	...
 	auto c =3D new C(1);
 This is one great advantage of static languages, that the compiler know=


helpful? I simply find the following stupid (I mean it's job for a machine,= not for a programmer):
 	class C {
 	    int i;
 	    this (int i) {this.i =3D i;}
 	}
 As we already enjoy this feature for structs...
=20

Again: Is that a common case? A constructor (probably with multiple argum=

 that all just set the corresponding fields of the object?

Depends on coding style, probably. If two element mean something together a= s a whole, I like to put them together.
 However, I agree that all that this.i =3D i; is tedious.
 As I have suggested before in another thread (and Simen did in this threa=

 something like
=20
 this( int this.i, float this.y, Foo f) {
      // f is no field of the class.
      this.b =3D new Bar(f, i);
 }
=20
 would be helpful because you could mix arguments that are just passed wit=

 arguments you want to use in the constructor without too much writing ove=

Yes, I like this very much. It lets clearly tell apart which params are in = fact fields, and which ones are params properly speaking. Denis -- -- -- -- -- -- -- vit esse estrany =E2=98=A3 spir.wikidot.com
Nov 11 2010
prev sibling parent spir <denis.spir gmail.com> writes:
On Thu, 11 Nov 2010 18:53:56 +0100
Daniel Gibson <metalcaedes gmail.com> wrote:

 That being said, I'm really ambivalent on whether this needs to be=20
 included.  It's not that terrible that you have to parenthesize properl=


=20
 Also, I'm not sure if this is a common case.. although I had similar situ=

 as well (it was more like (new Cursor(somecollection)).where(...).select(=

 with where() and select() returning a Cursor that wrapped/used the preced=

 cursor.. and also it was Java).
=20
 But I don't know if this is useful for other kinds of code that don't dea=

 collections or similar stuff.

This use case is probably not important enough (even if I use it often :-) = to impulse any change in the language. You are right. (I was just showing t= hat "new", in addition to not bringing much, if anything, to the language, = can make nice code less readable.) Denis -- -- -- -- -- -- -- vit esse estrany =E2=98=A3 spir.wikidot.com
Nov 11 2010