Jump to page: 1 26  
Page
Thread overview
Named constructors
Jan 09, 2019
Dru
Jan 09, 2019
Alex
Jan 09, 2019
bauss
Jan 09, 2019
JN
Jan 09, 2019
Neia Neutuladh
Jan 09, 2019
JN
Jan 09, 2019
Neia Neutuladh
Jan 10, 2019
evilrat
Jan 10, 2019
Dru
Jan 10, 2019
evilrat
Jan 10, 2019
Simen Kjærås
Jan 09, 2019
Neia Neutuladh
Jan 09, 2019
Daniel Kozak
Jan 09, 2019
12345swordy
Jan 09, 2019
Daniel Kozák
Jan 09, 2019
12345swordy
Jan 09, 2019
Atila Neves
Jan 09, 2019
H. S. Teoh
Jan 10, 2019
Atila Neves
Jan 10, 2019
evilrat
Jan 10, 2019
Atila Neves
Jan 10, 2019
JN
Jan 10, 2019
H. S. Teoh
Jan 10, 2019
JN
Jan 10, 2019
Ali Çehreli
Jan 10, 2019
Neia Neutuladh
Jan 10, 2019
Atila Neves
Jan 14, 2019
aliak
Jan 14, 2019
Atila Neves
Jan 14, 2019
12345swordy
Jan 15, 2019
Olivier FAURE
Jan 15, 2019
Atila Neves
Jan 14, 2019
Jacob Carlborg
Jan 15, 2019
aliak
Jan 11, 2019
rikki cattermole
Jan 11, 2019
JN
Jan 11, 2019
rikki cattermole
Jan 11, 2019
JN
Jan 11, 2019
rikki cattermole
Jan 10, 2019
Neia Neutuladh
Jan 10, 2019
John Colvin
Jan 10, 2019
H. S. Teoh
Jan 10, 2019
Atila Neves
Jan 10, 2019
H. S. Teoh
Jan 10, 2019
Atila Neves
Jan 10, 2019
H. S. Teoh
Jan 13, 2019
Jacob Carlborg
Jan 14, 2019
Atila Neves
Jan 14, 2019
Jacob Carlborg
Jan 15, 2019
Atila Neves
Jan 10, 2019
Atila Neves
Jan 10, 2019
jmh530
Jan 10, 2019
Walter Bright
January 09, 2019
Another way to distinguish between constructors is needed.
Because it is possible to have two different constructors that take the same arguments.
Adding dummy arguments that are unused hurts code clarity.


January 09, 2019
On Wednesday, 9 January 2019 at 07:47:02 UTC, Dru wrote:
> Another way to distinguish between constructors is needed.
> Because it is possible to have two different constructors that take the same arguments.
> Adding dummy arguments that are unused hurts code clarity.

Couldn't this problem be solved by a factory method? I mean, either this, or something like this: http://www.cs.technion.ac.il/users/yechiel/c++-faq/named-ctor-idiom.html

´´´
import std.stdio;
import std.math;

void main()
{
    auto pr = Point.rectangular(2,3);

    assert(approxEqual(pr.x_, 2));
    assert(approxEqual(pr.y_, 3));

    auto pp = Point.polar(1,PI);

    assert(approxEqual(pp.x_, -1));
    assert(approxEqual(pp.y_, 0));
}


struct Point {
public:
  static Point rectangular(real x, real y)      // Rectangular coord's
  {
      return Point(x,y);
  }
  static Point polar(real radius, real angle)   // Polar coordinates
  {
      return Point(radius * cos(angle), radius * sin(angle));
  }

private:
  this(real x, real y)
  {
      x_ = x;
      y_ = y;
  }
  real x_, y_;
}
´´´
January 09, 2019
On Wednesday, 9 January 2019 at 08:53:40 UTC, Alex wrote:
> On Wednesday, 9 January 2019 at 07:47:02 UTC, Dru wrote:
>> Another way to distinguish between constructors is needed.
>> Because it is possible to have two different constructors that take the same arguments.
>> Adding dummy arguments that are unused hurts code clarity.
>
> Couldn't this problem be solved by a factory method? I mean, either this, or something like this: http://www.cs.technion.ac.il/users/yechiel/c++-faq/named-ctor-idiom.html
>
> ´´´
> import std.stdio;
> import std.math;
>
> void main()
> {
>     auto pr = Point.rectangular(2,3);
>
>     assert(approxEqual(pr.x_, 2));
>     assert(approxEqual(pr.y_, 3));
>
>     auto pp = Point.polar(1,PI);
>
>     assert(approxEqual(pp.x_, -1));
>     assert(approxEqual(pp.y_, 0));
> }
>
>
> struct Point {
> public:
>   static Point rectangular(real x, real y)      // Rectangular coord's
>   {
>       return Point(x,y);
>   }
>   static Point polar(real radius, real angle)   // Polar coordinates
>   {
>       return Point(radius * cos(angle), radius * sin(angle));
>   }
>
> private:
>   this(real x, real y)
>   {
>       x_ = x;
>       y_ = y;
>   }
>   real x_, y_;
> }
> ´´´

I like this approach to it and you're entirely correct.

It would be nice with support for this in the language without having to create factory methods.

Basically something like the following could be lowered to your code.

´´´
import std.stdio;
import std.math;

void main()
{
    auto pr = Point.rectangular(2,3);

    assert(approxEqual(pr.x_, 2));
    assert(approxEqual(pr.y_, 3));

    auto pp = Point.polar(1,PI);

    assert(approxEqual(pp.x_, -1));
    assert(approxEqual(pp.y_, 0));
}


struct Point {
public:
  this(real x, real y)
  {
      this.x = x;
      this.y = y;
  }

  this rectangular(real x, real y)
  {
      this(x,y);
  }

  this polar(real radius, real angle)
  {
      this(radius * cos(angle), radius * sin(angle));
  }

  real x, y;
}
´´´
January 09, 2019
On Wed, 09 Jan 2019 08:53:40 +0000, Alex wrote:
> On Wednesday, 9 January 2019 at 07:47:02 UTC, Dru wrote:
>> Another way to distinguish between constructors is needed. Because it
>> is possible to have two different constructors that take the same
>> arguments.
>> Adding dummy arguments that are unused hurts code clarity.
> 
> Couldn't this problem be solved by a factory method? I mean,
> either this, or something like this:
> http://www.cs.technion.ac.il/users/yechiel/c++-faq/named-ctor-idiom.html

A constructor can alter const fields, but a factory method can't, so they're not exactly equivalent. I was hoping you could add a template parameter to a constructor to give a "name" to it, like:

class Foo
{
  const int i;
  this(string name: "shift")(int i) { this.i = 1 << i; }
  this(string name: "direct")(int i) { this.i = i; }
}
new Foo!"shift"(3);

But that doesn't work; there is no way to explicitly provide template parameters to a constructor.
January 09, 2019
On Wednesday, 9 January 2019 at 07:47:02 UTC, Dru wrote:
> Another way to distinguish between constructors is needed.
> Because it is possible to have two different constructors that take the same arguments.
> Adding dummy arguments that are unused hurts code clarity.

Adding dummy arguments is unecessary. Just use the type system:

struct Person {
    this(FirstName firstName, LastName lastName) { /* ... */ }
}

struct FirstName { string value; }
struct LastName  { string value; }


C++ even has two libraries to do this, but D doesn't need that given that structs in D are much more useful (no need to write a constructor).
January 09, 2019
On Wed, Jan 09, 2019 at 05:30:32PM +0000, Atila Neves via Digitalmars-d wrote:
> On Wednesday, 9 January 2019 at 07:47:02 UTC, Dru wrote:
> > Another way to distinguish between constructors is needed.  Because it is possible to have two different constructors that take the same arguments.  Adding dummy arguments that are unused hurts code clarity.
> 
> Adding dummy arguments is unecessary. Just use the type system:
> 
> struct Person {
>     this(FirstName firstName, LastName lastName) { /* ... */ }
> }
> 
> struct FirstName { string value; }
> struct LastName  { string value; }

+1. That's what the type system is for.  Dummy arguments are NEVER a good idea unless there's a need for the API to be uniform.

It also makes the calling code self-documenting without needing language support for named arguments:

	auto myPerson = Person(FirstName("John"), LastName("Doe"));

rather than the opaque (and thus error-prone):

	// Bug 1234: hmm, is it first name first, or last name first?
	//auto myPerson = Person("Doe", "John");
	auto myPerson = Person("John", "Doe");


T

-- 
Bare foot: (n.) A device for locating thumb tacks on the floor.
January 09, 2019
On Wed, Jan 9, 2019 at 5:50 PM Neia Neutuladh via Digitalmars-d < digitalmars-d@puremagic.com> wrote:

> On Wed, 09 Jan 2019 08:53:40 +0000, Alex wrote:
> > On Wednesday, 9 January 2019 at 07:47:02 UTC, Dru wrote:
> >> Another way to distinguish between constructors is needed. Because it
> >> is possible to have two different constructors that take the same
> >> arguments.
> >> Adding dummy arguments that are unused hurts code clarity.
> >
> > Couldn't this problem be solved by a factory method? I mean,
> > either this, or something like this:
> > http://www.cs.technion.ac.il/users/yechiel/c++-faq/named-ctor-idiom.html
>
> A constructor can alter const fields, but a factory method can't, so they're not exactly equivalent. I was hoping you could add a template parameter to a constructor to give a "name" to it, like:
>
> class Foo
> {
>   const int i;
>   this(string name: "shift")(int i) { this.i = 1 << i; }
>   this(string name: "direct")(int i) { this.i = i; }
> }
> new Foo!"shift"(3);
>
> But that doesn't work; there is no way to explicitly provide template parameters to a constructor.
>

import std.stdio;
import std.math;

void main()
{
    auto sa = S.constructorA(3,4);
    auto sb = S.constructorB(3,4);
    writeln(sa);
    writeln(sb);
}


struct S {
public:
   this(string name: "constructorA")(real x, real y)
   {
       this.x = x;
       this.y = y;
   }

   this(string name: "constructorB")(real x, real z)
   {
       this.x = x;
       this.z = z;
   }

   static constructorA(Args...)(Args args)
   {
       S s;
       s.__ctor!"constructorA"(args);
       return s;
   }

   static constructorB(Args...)(Args args)
   {
       S s;
       s.__ctor!"constructorB"(args);
       return s;
   }
   const real x, y, z;
}


January 09, 2019
On Wednesday, 9 January 2019 at 18:19:35 UTC, Daniel Kozak wrote:
> On Wed, Jan 9, 2019 at 5:50 PM Neia Neutuladh via Digitalmars-d < digitalmars-d@puremagic.com> wrote:
>
>>[...]
>
> import std.stdio;
> import std.math;
>
> void main()
> {
>     auto sa = S.constructorA(3,4);
>     auto sb = S.constructorB(3,4);
>     writeln(sa);
>     writeln(sb);
> }
>
>
> struct S {
> public:
>    this(string name: "constructorA")(real x, real y)
>    {
>        this.x = x;
>        this.y = y;
>    }
>
>    this(string name: "constructorB")(real x, real z)
>    {
>        this.x = x;
>        this.z = z;
>    }
>
>    static constructorA(Args...)(Args args)
>    {
>        S s;
>        s.__ctor!"constructorA"(args);
>        return s;
>    }
>
>    static constructorB(Args...)(Args args)
>    {
>        S s;
>        s.__ctor!"constructorB"(args);
>        return s;
>    }
>    const real x, y, z;
> }
That solution has a compile time cost.
January 09, 2019
On Wednesday, 9 January 2019 at 18:24:28 UTC, 12345swordy wrote:
> That solution has a compile time cost.

I do not see any compile time cost, what do you mean?


January 09, 2019
On Wednesday, 9 January 2019 at 10:02:12 UTC, bauss wrote:
>
> I like this approach to it and you're entirely correct.
>
> It would be nice with support for this in the language without having to create factory methods.
>
> Basically something like the following could be lowered to your code.

I was going to say that this post will be mostly ignored and people will present some template magic to partially implement such feature (just add few imports and some boilerplate code), but I guess I got beaten to it :)
« First   ‹ Prev
1 2 3 4 5 6