www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - new A().b() currently requires extra brackets/parentheses

reply Ben Davis <entheh cantab.net> writes:
Hi,

I'm trying to define an API in D where an object can be instantiated and 
then set up inline. I have various methods that return 'this' so that 
they can be used inline in this way. For example:

dialogue=new GuiDialogue([
	(new GuiLabel(titleText)).setLayoutHint(GuiLayoutHint.TOP),
	fileNameInput.setLayoutHint(GuiLayoutHint.TOP),
	currentDirectoryLabel.setLayoutHint(GuiLayoutHint.TOP),
	confirmButton,
	new GuiButton("Cancel",delegate {dialogue=null;}),
]);

D's syntax currently requires me to put the new A() part in brackets. So 
instead of

new A().b()

I have to write

(new A()).b()

If I don't do that, then the error is "found . when expecting ," - which 
sounds as if it's already decided it's finished reading the expression, 
so there isn't a problem with ambiguity. (I suppose if the brackets are 
optional, then "new A.b()" would be ambiguous, but this is no different 
from the 'else' binding problem.)

So - is this something that could be relaxed?

Thanks,

Ben :)
Sep 09 2012
next sibling parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Sun, Sep 9, 2012 at 2:49 PM, Ben Davis <entheh cantab.net> wrote:

 D's syntax currently requires me to put the new A() part in brackets. So
 instead of

 new A().b()

 I have to write

 (new A()).b()

Hi Ben, you could use factory functions: class A {} A a() { return new A();} (and appropriate overloads for the different A constructors, of course). Which would give you: dialogue=guiDialogue([ guiLabel(titleText).setLayoutHint(GuiLayoutHint.TOP), fileNameInput.setLayoutHint(GuiLayoutHint.TOP), currentDirectoryLabel.setLayoutHint(GuiLayoutHint.TOP), confirmButton, guiButton("Cancel", {dialogue=null;}), ]); For the delegate at the end, I *guess* (but I'm not certain) that just using { ... } will work. It's a void delegate(). Then:
Sep 09 2012
parent reply Ben Davis <entheh cantab.net> writes:
Hi,

On 09/09/2012 14:23, Philippe Sigaud wrote:
 you could use factory functions:

 class A {}

 A a() { return new A();}

Good idea. It might not work so well for me because the user might also be creating custom GUI components and would therefore have to create their own factory functions, but thanks for the idea in any case.
 For the delegate at the end, I *guess* (but I'm not certain) that just
 using { ... } will work. It's a void delegate().

You're right - it does compile without the keyword. Thanks again :) Ben :)
Sep 09 2012
parent reply Nick Treleaven <ntrel-public yahoo.co.uk> writes:
On 09/09/2012 14:39, Ben Davis wrote:
 On 09/09/2012 14:23, Philippe Sigaud wrote:
  > you could use factory functions:
  >
  > class A {}
  >
  > A a() { return new A();}

 Good idea. It might not work so well for me because the user might also
 be creating custom GUI components and would therefore have to create
 their own factory functions, but thanks for the idea in any case.

Maybe you could use a template: auto create(T, Args...)(Args args) { return new T(args); } class A { int i; this(int i){this.i = i;} } import std.stdio; void main() { create!A(5).i.writeln(); } But I agree with you it would be nice if dmd supported 'new A().b()'.
Sep 09 2012
next sibling parent Jacob Carlborg <doob me.com> writes:
On 2012-09-09 17:16, Nick Treleaven wrote:

 But I agree with you it would be nice if dmd supported 'new A().b()'.

This would be good for DWT as well, since this is legal in Java. -- /Jacob Carlborg
Sep 09 2012
prev sibling parent Nick Treleaven <ntrel-public yahoo.co.uk> writes:
On 09/09/2012 18:25, Philippe Sigaud wrote:
 On Sun, Sep 9, 2012 at 5:16 PM, Nick Treleaven <ntrel-public yahoo.co.uk>
wrote:

 Maybe you could use a template:

 auto create(T, Args...)(Args args)
 {
      return new T(args);
 }

 class A
 {
      int i;
      this(int i){this.i = i;}
 }

 import std.stdio;

 void main()
 {
      create!A(5).i.writeln();
 }

A generic 'create' template would be good for generic code: on a reference type, use 'new' and pass args, whereas for a value type, use the type directly. Of course, this should manage builtins (like int, int[], int[3]) correctly.

I assumed he only needed class construction. I forgot that we already have std.container.make (which also works with structs): make!A(5).i.writeln(); I noticed jmdavis has a pull request for what you describe: https://github.com/D-Programming-Language/phobos/pull/756
Sep 10 2012
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 09/09/2012 02:49 PM, Ben Davis wrote:
 Hi,

 I'm trying to define an API in D where an object can be instantiated and
 then set up inline. I have various methods that return 'this' so that
 they can be used inline in this way. For example:

 dialogue=new GuiDialogue([
      (new GuiLabel(titleText)).setLayoutHint(GuiLayoutHint.TOP),
      fileNameInput.setLayoutHint(GuiLayoutHint.TOP),
      currentDirectoryLabel.setLayoutHint(GuiLayoutHint.TOP),
      confirmButton,
      new GuiButton("Cancel",delegate {dialogue=null;}),
 ]);

 D's syntax currently requires me to put the new A() part in brackets. So
 instead of

 new A().b()

 I have to write

 (new A()).b()

 If I don't do that, then the error is "found . when expecting ," - which
 sounds as if it's already decided it's finished reading the expression,
 so there isn't a problem with ambiguity. (I suppose if the brackets are
 optional, then "new A.b()" would be ambiguous, but this is no different
 from the 'else' binding problem.)

 So - is this something that could be relaxed?

 Thanks,

 Ben :)

I think so. Probably it is just a bug. (the spec does not indicate that it is illegal iirc.) Maybe you can even fix it yourself, the parser should be quite hackable.
Sep 09 2012
next sibling parent reply Ben Davis <entheh cantab.net> writes:
On 09/09/2012 14:28, Timon Gehr wrote:
 I think so. Probably it is just a bug. (the spec does not indicate that
 it is illegal iirc.) Maybe you can even fix it yourself, the parser
 should be quite hackable.

That's good to hear - but since I'm only using D for a project outside of work, and have very little time for it as it is, I don't think I can offer to fix it. I'll probably just use the brackets for now. :)
Sep 09 2012
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 09/09/2012 03:40 PM, Ben Davis wrote:
 On 09/09/2012 14:28, Timon Gehr wrote:
 I think so. Probably it is just a bug. (the spec does not indicate that
 it is illegal iirc.) Maybe you can even fix it yourself, the parser
 should be quite hackable.

That's good to hear - but since I'm only using D for a project outside of work, and have very little time for it as it is, I don't think I can offer to fix it. I'll probably just use the brackets for now. :)

OK, I'll give it a try and maybe submit a pull request.
Sep 09 2012
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 09/09/2012 03:28 PM, Timon Gehr wrote:
 ...

 I think so. Probably it is just a bug. (the spec does not indicate that
 it is illegal iirc.)

I was wrong, the grammar actually precludes this, so it has to be changed as well. Anyway, this is the pull request: https://github.com/D-Programming-Language/dmd/pull/1111
Sep 09 2012
parent reply =?ISO-8859-1?Q?S=F6nke_Ludwig?= <sludwig outerproduct.org> writes:
Am 09.09.2012 16:43, schrieb Timon Gehr:
 On 09/09/2012 03:28 PM, Timon Gehr wrote:
 ...

 I think so. Probably it is just a bug. (the spec does not indicate that
 it is illegal iirc.)

I was wrong, the grammar actually precludes this, so it has to be changed as well. Anyway, this is the pull request: https://github.com/D-Programming-Language/dmd/pull/1111

Does the following also work? class A { static class B { int x; } } new A.B.x = 1;
Sep 10 2012
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 09/10/2012 09:01 AM, Sönke Ludwig wrote:
 Am 09.09.2012 16:43, schrieb Timon Gehr:
 On 09/09/2012 03:28 PM, Timon Gehr wrote:
 ...

 I think so. Probably it is just a bug. (the spec does not indicate that
 it is illegal iirc.)

I was wrong, the grammar actually precludes this, so it has to be changed as well. Anyway, this is the pull request: https://github.com/D-Programming-Language/dmd/pull/1111

Does the following also work? class A { static class B { int x; } } new A.B.x = 1;

A.B.x is not a type. new A.B().x = 1 works.
Sep 10 2012
parent =?ISO-8859-1?Q?S=F6nke_Ludwig?= <sludwig outerproduct.org> writes:
Am 10.09.2012 15:39, schrieb Timon Gehr:
 On 09/10/2012 09:01 AM, Sönke Ludwig wrote:
 Am 09.09.2012 16:43, schrieb Timon Gehr:
 On 09/09/2012 03:28 PM, Timon Gehr wrote:
 ...

 I think so. Probably it is just a bug. (the spec does not indicate that
 it is illegal iirc.)

I was wrong, the grammar actually precludes this, so it has to be changed as well. Anyway, this is the pull request: https://github.com/D-Programming-Language/dmd/pull/1111

Does the following also work? class A { static class B { int x; } } new A.B.x = 1;

A.B.x is not a type. new A.B().x = 1 works.

Of course it's not a type... but A.B is. It's also not that important, but it feels slightly inconsistent and coincidential that the clamps are used here to separate the new expression from the rest.
Sep 10 2012
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 9/10/12, S=F6nke Ludwig <sludwig outerproduct.org> wrote:
 Of course it's not a type... but A.B is. It's also not that important,
 but it feels slightly inconsistent and coincidential that the clamps are
 used here to separate the new expression from the rest.

It prevents ambiguity and hijacking. If 'x' of B ends up being a type or an alias of a type you'll end up instantiating something else instead of the B class.
Sep 10 2012
prev sibling next sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Sun, Sep 9, 2012 at 5:16 PM, Nick Treleaven <ntrel-public yahoo.co.uk> wrote:

 Maybe you could use a template:

 auto create(T, Args...)(Args args)
 {
     return new T(args);
 }

 class A
 {
     int i;
     this(int i){this.i = i;}
 }

 import std.stdio;

 void main()
 {
     create!A(5).i.writeln();
 }

A generic 'create' template would be good for generic code: on a reference type, use 'new' and pass args, whereas for a value type, use the type directly. Of course, this should manage builtins (like int, int[], int[3]) correctly.
Sep 09 2012
prev sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Mon, Sep 10, 2012 at 7:38 PM, Nick Treleaven
<ntrel-public yahoo.co.uk> wrote:

 I assumed he only needed class construction. I forgot that we already have
 std.container.make (which also works with structs):

Oh, I wasn't criticizing your code, just listing my needs :) I didn't know about std.container.make.
 make!A(5).i.writeln();

 I noticed jmdavis has a pull request for what you describe:
 https://github.com/D-Programming-Language/phobos/pull/756

Good!
Sep 10 2012