January 09, 2019
On Wed, 09 Jan 2019 20:54:48 +0000, JN wrote:
> 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 :)

It's handy when writing the DIP to have as many workarounds as possible. Then you can show why they aren't good enough in advance and save a round of drafts.
January 09, 2019
On Wednesday, 9 January 2019 at 19:04:33 UTC, Daniel Kozák wrote:
> 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?

You are using templates in that code, that going to have compile time associated with it(especially recursive templates).

Regardless, your code uses the hidden symbol ._ctor! Which if you find yourself in a such situation then something is severely wrong.

Alex
January 09, 2019
On Wednesday, 9 January 2019 at 21:41:34 UTC, Neia Neutuladh wrote:
> On Wed, 09 Jan 2019 20:54:48 +0000, JN wrote:
>> 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 :)
>
> It's handy when writing the DIP to have as many workarounds as possible. Then you can show why they aren't good enough in advance and save a round of drafts.

Perhaps, but sometimes it feels like the language features are set in stone at this point. As long as you can implement a language feature X with template magic, even if it's partially implementing X, it will be used as an excuse why X shouldn't be a language feature.

I mean, I see the benefits of a lightweight language with powerful metaprogramming features, but I am also wary of it ending up with a Lisp Curse ( http://www.winestockwebdesign.com/Essays/Lisp_Curse.html - especially the part with "Imagine that a strong rivalry develops between Haskell and Common Lisp. What happens next?" ).

Some language features are almost straight syntax sugar, and there's nothing wrong with that either. Consider foreach in D. I am sure it could be implemented with a few mixins, and yet, it is a language feature.
January 09, 2019
On Wed, 09 Jan 2019 21:52:00 +0000, JN wrote:
> Perhaps, but sometimes it feels like the language features are set in stone at this point. As long as you can implement a language feature X with template magic, even if it's partially implementing X, it will be used as an excuse why X shouldn't be a language feature.

Things that give a little benefit over a template solution are guaranteed to be rejected. The solutions for named constructors are pretty clunky, on the other hand, either requiring use of reserved symbols or not supporting const fields, so a named constructors DIP is only likely to be rejected.
January 10, 2019
On Wednesday, 9 January 2019 at 20:54:48 UTC, JN wrote:
> 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 :)

Surprisingly no one was thinking about tags...

Here is the one without templates


struct Stuff_Normal {}
struct Stuff_Special {}

struct Stuff
{

  this(Stuff_Normal _, float x, float y) { ... }
  this(Stuff_Special _, float x, float y) { ... }
}

usage

  auto val = Stuff(Stuff_Normal(), 1, 2);


But honestly Atila version with distinct types was the best IMHO, because you know, one doesn't want to add temperature to angle or length to money
January 10, 2019
On Wednesday, 9 January 2019 at 20:54:48 UTC, JN wrote:
> 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 :)

Since those templates are my specialty, here's my go:

struct Point {
    this(string s : "rectangular")(real x, real y) { /* ... */ }
    this(string s : "polar") (real r, real theta)  { /* ... */ }
}

struct make(T) {
    @disable this();
    static T opDispatch(string name, Args...)(Args args) {
        T result;
        result.__ctor!name(args);
        return result;
    }
}

unittest {
    auto a = make!Point.rectangular(1,2);
    auto b = make!Point.polar(1,2);
}

--
  Simen
January 10, 2019
On Wednesday, 9 January 2019 at 17:46:52 UTC, H. S. Teoh wrote:
> On Wed, Jan 09, 2019 at 05:30:32PM +0000, Atila Neves via Digitalmars-d wrote:
>> [...]
>
> +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

Fully in agreement. Now if only I write that library I've been meaning to that lets you pass parameters in any order if the types are right...
January 10, 2019
On Thursday, 10 January 2019 at 10:50:24 UTC, Atila Neves wrote:
> On Wednesday, 9 January 2019 at 17:46:52 UTC, H. S. Teoh wrote:
>> On Wed, Jan 09, 2019 at 05:30:32PM +0000, Atila Neves via Digitalmars-d wrote:
>>> [...]
>>
>> +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
>
> Fully in agreement. Now if only I write that library I've been meaning to that lets you pass parameters in any order if the types are right...

For that I'd actually would prefer having a language support - named parameters, like Python/C# does...

   void someFunc(string firstName, string lastName, int age);

   // use it
   someFunc(age=30, firstName="John", lastName="Doe");

That also solves the problem when we have some default parameters and only want to pass one of them from middle/end of the list.
January 10, 2019
On Thursday, 10 January 2019 at 10:50:24 UTC, Atila Neves wrote:
> On Wednesday, 9 January 2019 at 17:46:52 UTC, H. S. Teoh wrote:
>> [...]
>
> Fully in agreement. Now if only I write that library I've been meaning to that lets you pass parameters in any order if the types are right...

And doesn't cause compile times to explode?

:)
January 10, 2019
On 1/9/2019 9:46 AM, H. S. Teoh wrote:
> It also makes the calling code self-documenting without needing language
> support for named arguments:
> 
> 	auto myPerson = Person(FirstName("John"), LastName("Doe"));

Nailed it :-)