Re: Rebind template(bug?)

2016-08-23 Thread Jack Applegame via Digitalmars-d-learn

On Monday, 22 August 2016 at 21:46:35 UTC, Engine Machine wrote:

I'm sorry if it confuses you... it doesn't confuse me.

Confuses? No.
I do not know why you have to try and prove something that is a 
preference. Do you often get in to arguments with people about 
how ford is better than chevy or blonds are better than 
brunettes?
You're wrong again. I don't try to prove anything, just answer 
your questions.

But finally I understood your main goal:
You don't want to see more than one 'class' keyword. You want 
that recursive class template automatically stops inheritance 
without any additional moves, such as specializations, static ifs 
and so on.





Re: Rebind template(bug?)

2016-08-22 Thread ag0aep6g via Digitalmars-d-learn

On 08/23/2016 03:23 AM, Engine Machine wrote:

On Monday, 22 August 2016 at 22:52:28 UTC, ag0aep6g wrote:

[...]

Simply not replying is an option, too. It may be a bit less
polite, but it's better than escalating things.


True, but then you should also take your own advice.


Yeah, I'm going to do that from now on regarding posts of yours.


Re: Rebind template(bug?)

2016-08-22 Thread Engine Machine via Digitalmars-d-learn

On Monday, 22 August 2016 at 22:52:28 UTC, ag0aep6g wrote:

On Monday, 22 August 2016 at 21:46:35 UTC, Engine Machine wrote:

I'm sorry if it confuses you... it doesn't confuse me.


You needed quite some help to get this thing to work. And you 
made some mistakes and wrong statements in the process. That's 
perfectly fine, but please don't act as if Jack is the 
simpleton while you're the brainiac.




Um, please don't be an arrogant prick. I never said anything 
about that. He says it confuses him, I said it doesn't confuse 
me. Getting it to work in D has nothing to do with understanding 
the structure. It's like saying that because you can't understand 
English that you must be an imbecile.



I do not know why you have to try and prove something that is 
a preference.


Jack showed a version which he thinks is "cleaner". And since 
this is a discussion board about code, it makes perfect sense 
for him to do that. If you don't care about it, you don't have 
to engage in discussion, of course.




So? I am the one that asked the question how to do X. He brings 
up Y, then you try to justify Y. It is illogical and insane to do 
so.


Do you often get in to arguments with people about how ford is 
better than chevy or blonds are better than brunettes?


Please don't take this to a personal level. Jack was talking 
about the code, and you start questioning his character. Not 
cool.


No, Jack is talking about Y and people that try to change topics, 
like you have done, is insane and do the same thing with what I 
have stated. Keep it up though.


If you're happy with what you got, and you don't want to 
discuss other versions, you can say so without setting the 
stage for a shouting match. Simply not replying is an option, 
too. It may be a bit less polite, but it's better than 
escalating things.


True, but then you should also take your own advice. But if a 
person can't be direct, honest, and talk specifically what is 
asked about, then it is already the well is already poisoned. But 
which will you option will you choose?







Re: Rebind template(bug?)

2016-08-22 Thread ag0aep6g via Digitalmars-d-learn

On Monday, 22 August 2016 at 21:46:35 UTC, Engine Machine wrote:

I'm sorry if it confuses you... it doesn't confuse me.


You needed quite some help to get this thing to work. And you 
made some mistakes and wrong statements in the process. That's 
perfectly fine, but please don't act as if Jack is the simpleton 
while you're the brainiac.


I do not know why you have to try and prove something that is a 
preference.


Jack showed a version which he thinks is "cleaner". And since 
this is a discussion board about code, it makes perfect sense for 
him to do that. If you don't care about it, you don't have to 
engage in discussion, of course.


Do you often get in to arguments with people about how ford is 
better than chevy or blonds are better than brunettes?


Please don't take this to a personal level. Jack was talking 
about the code, and you start questioning his character. Not cool.


If you're happy with what you got, and you don't want to discuss 
other versions, you can say so without setting the stage for a 
shouting match. Simply not replying is an option, too. It may be 
a bit less polite, but it's better than escalating things.


Re: Rebind template(bug?)

2016-08-22 Thread Engine Machine via Digitalmars-d-learn

On Monday, 22 August 2016 at 19:09:34 UTC, Jack Applegame wrote:

On Monday, 22 August 2016 at 18:04:43 UTC, Engine Machine wrote:

How do you seriously think this is cleaner/simpler?

1. No extra encrypted things, such as InstantiateOrEmptySeq
2. Much more understandable.


You have two classes.
No. I have one template with two specializations. Class 
template and class is not the same thing.



Their is no uniformity between them.

They have the same name. This is the best uniformity.

You have uniformity between all the derived classes then have 
a special case for the base class. A certain easy to follow 
pattern is set up but needlessly break it for one case. Why?
Because it is the base class. It has no parent. Also this is 
the standard and well known pattern in template metaprogramming.


I'm sorry if it confuses you... it doesn't confuse me. I do not 
know why you have to try and prove something that is a 
preference. Do you often get in to arguments with people about 
how ford is better than chevy or blonds are better than brunettes?


Re: Rebind template(bug?)

2016-08-22 Thread Jack Applegame via Digitalmars-d-learn

On Monday, 22 August 2016 at 19:56:08 UTC, ag0aep6g wrote:
So this is just to avoid typing out `class Pug : Dog {...} 
class Dog : Animal {...} class Animal {...}`?
This allows you to create different inheritance chains with the 
same components quickly and easily. I don't know any use case, 
but looks funny:


T!("Animal", "Dog", "Pug") pug1;
T!("Life", "Animal", "Four-legged", "Pug") pug2;
T!("Dog", "Small", "Pug", ) smallPug;



Re: Rebind template(bug?)

2016-08-22 Thread ag0aep6g via Digitalmars-d-learn

On 08/22/2016 08:54 PM, Engine Machine wrote:

Yeah, but a name means nothing. Change it if you want ;)


Even with a better name it still requires a good amount of thinking by 
the reader to see what's going on.


[...]

What it achieves is a uniform way to create a hierarchical relationship
without excessive verbosity.

[...]

Ultimately it is just syntax, it does nothing over what D already does.
It doesn't create anything new. In some cases it simplifies. If it does,
then great, if it doesn't then don't use it. While I would prefer a
totally different syntax, I also like to keep things organized. Having
multiple classes floating around for certain things is just not needed
so there should be an option.


So this is just to avoid typing out `class Pug : Dog {...} class Dog : 
Animal {...} class Animal {...}`? If so, I don't think it's worth the 
hassle. At least in the version so far, it doesn't seem to really cut 
down on the typing.


Re: Rebind template(bug?)

2016-08-22 Thread Jack Applegame via Digitalmars-d-learn

On Monday, 22 August 2016 at 18:48:12 UTC, ag0aep6g wrote:
You can take this further with template constraints. Gives it a 
more uniform appearance at the price of some repetition:



class T()
{
int x;
}

class T(A...) : T!(A[0..$-1])
if (A.length > 0 && A[$-1] == "Animal")
{
int y;
}

class T(A...) : T!(A[0..$-1])
if (A.length > 0 && A[$-1] == "Dog")
{
int z;
}

class T(A...) : T!(A[0..$-1])
if (A.length > 0 && A[$-1] == "Pug")
{
int s;
}
Yes. And even simpler, if to change the order of template 
parameters:


class T() {
int x;
}

class T(string type : "Animal", A...) : T!A {
int y;
}

class T(string type : "Dog", A...) : T!A {
int z;
}

class T(string type : "Pug", A...) : T!A {
int s;
}


Re: Rebind template(bug?)

2016-08-22 Thread Jack Applegame via Digitalmars-d-learn

On Monday, 22 August 2016 at 18:04:43 UTC, Engine Machine wrote:

How do you seriously think this is cleaner/simpler?

1. No extra encrypted things, such as InstantiateOrEmptySeq
2. Much more understandable.


You have two classes.
No. I have one template with two specializations. Class template 
and class is not the same thing.



Their is no uniformity between them.

They have the same name. This is the best uniformity.

You have uniformity between all the derived classes then have a 
special case for the base class. A certain easy to follow 
pattern is set up but needlessly break it for one case. Why?
Because it is the base class. It has no parent. Also this is the 
standard and well known pattern in template metaprogramming.





Re: Rebind template(bug?)

2016-08-22 Thread Engine Machine via Digitalmars-d-learn

On Monday, 22 August 2016 at 18:48:12 UTC, ag0aep6g wrote:

On 08/22/2016 08:04 PM, Engine Machine wrote:
How do you seriously think this is cleaner/simpler? You have 
two
classes. Their is no uniformity between them. You have 
uniformity
between all the derived classes then have a special case for 
the base
class. A certain easy to follow pattern is set up but 
needlessly break

it for one case. Why?


It avoids the relatively obscure (and badly named, by me) 
InstantiateOrEmptySeq template.


You can take this further with template constraints. Gives it a 
more uniform appearance at the price of some repetition:



class T()
{
int x;
}

class T(A...) : T!(A[0..$-1])
if (A.length > 0 && A[$-1] == "Animal")
{
int y;
}

class T(A...) : T!(A[0..$-1])
if (A.length > 0 && A[$-1] == "Dog")
{
int z;
}

class T(A...) : T!(A[0..$-1])
if (A.length > 0 && A[$-1] == "Pug")
{
int s;
}


I wouldn't say that this is obviously, objectively, 
significantly better than the version with the helper template, 
though.




Yeah, but a name means nothing. Change it if you want ;)


By the way, it's not obvious to me what this whole thing 
achieves in practice. And whatever benefit there is, it has to 
be weighed against the cost of the added complexity.


What it achieves is a uniform way to create a hierarchical 
relationship without excessive verbosity. Now, the static ifs are 
probably the most verbose part, a static switch would help:


static switch (A)
{
   case "Animal":
   return;
   ...
}


But only slightly.

I don't mean to say that this is not worth pursuing. Just a 
friendly reminder that over-engineering is something to look 
out for, from someone who is prone to over-engineering himself.



Ultimately it is just syntax, it does nothing over what D already 
does. It doesn't create anything new. In some cases it 
simplifies. If it does, then great, if it doesn't then don't use 
it. While I would prefer a totally different syntax, I also like 
to keep things organized. Having multiple classes floating around 
for certain things is just not needed so there should be an 
option.





Re: Rebind template(bug?)

2016-08-22 Thread ag0aep6g via Digitalmars-d-learn

On 08/22/2016 08:04 PM, Engine Machine wrote:

How do you seriously think this is cleaner/simpler? You have two
classes. Their is no uniformity between them. You have uniformity
between all the derived classes then have a special case for the base
class. A certain easy to follow pattern is set up but needlessly break
it for one case. Why?


It avoids the relatively obscure (and badly named, by me) 
InstantiateOrEmptySeq template.


You can take this further with template constraints. Gives it a more 
uniform appearance at the price of some repetition:



class T()
{
int x;
}

class T(A...) : T!(A[0..$-1])
if (A.length > 0 && A[$-1] == "Animal")
{
int y;
}

class T(A...) : T!(A[0..$-1])
if (A.length > 0 && A[$-1] == "Dog")
{
int z;
}

class T(A...) : T!(A[0..$-1])
if (A.length > 0 && A[$-1] == "Pug")
{
int s;
}


I wouldn't say that this is obviously, objectively, significantly better 
than the version with the helper template, though.


By the way, it's not obvious to me what this whole thing achieves in 
practice. And whatever benefit there is, it has to be weighed against 
the cost of the added complexity.


I don't mean to say that this is not worth pursuing. Just a friendly 
reminder that over-engineering is something to look out for, from 
someone who is prone to over-engineering himself.


Re: Rebind template(bug?)

2016-08-22 Thread Engine Machine via Digitalmars-d-learn

On Monday, 22 August 2016 at 07:54:36 UTC, Jack Applegame wrote:

On Monday, 22 August 2016 at 00:43:00 UTC, Engine Machine wrote:

The following code works and does what I want!

template InstantiateOrEmptySeq(alias tmpl, args...)
{
alias Seq(T...)=T;
static if (args.length > 0)
alias InstantiateOrEmptySeq = tmpl!(args[0 .. $-1]);
else
alias InstantiateOrEmptySeq = Seq!();
}


class T(A...) : InstantiateOrEmptySeq!(T, A)
{   
static if (A.length == 0)
{
// Base class
int x;
} else  
static if (A[$-1] == "Animal")
{
int y;
} else
static if (A[$-1] == "Dog")
{
int z;
} else
static if (A[$-1] == "Pug")
{
int s;
	} else static assert(A[$-1]~" not a defined class of 
"~this.stringof);

}


Why don't you like a cleaner (in my opinion) solution?

class T() {
// Base class
int x;
}

class T(A...) : T!(A[0..$-1]) { 
static if (A[$-1] == "Animal")
{
int y;
} else
static if (A[$-1] == "Dog")
{
int z;
} else
static if (A[$-1] == "Pug")
{
int s;
	} else static assert(A[$-1]~" not a defined class of 
"~this.stringof);

}


How do you seriously think this is cleaner/simpler? You have two 
classes. Their is no uniformity between them. You have uniformity 
between all the derived classes then have a special case for the 
base class. A certain easy to follow pattern is set up but 
needlessly break it for one case. Why?













Re: Rebind template(bug?)

2016-08-22 Thread Jack Applegame via Digitalmars-d-learn

On Monday, 22 August 2016 at 00:43:00 UTC, Engine Machine wrote:

The following code works and does what I want!

template InstantiateOrEmptySeq(alias tmpl, args...)
{
alias Seq(T...)=T;
static if (args.length > 0)
alias InstantiateOrEmptySeq = tmpl!(args[0 .. $-1]);
else
alias InstantiateOrEmptySeq = Seq!();
}


class T(A...) : InstantiateOrEmptySeq!(T, A)
{   
static if (A.length == 0)
{
// Base class
int x;
} else  
static if (A[$-1] == "Animal")
{
int y;
} else
static if (A[$-1] == "Dog")
{
int z;
} else
static if (A[$-1] == "Pug")
{
int s;
	} else static assert(A[$-1]~" not a defined class of 
"~this.stringof);

}


Why don't you like a cleaner (in my opinion) solution?

class T() {
// Base class
int x;
}

class T(A...) : T!(A[0..$-1]) { 
static if (A[$-1] == "Animal")
{
int y;
} else
static if (A[$-1] == "Dog")
{
int z;
} else
static if (A[$-1] == "Pug")
{
int s;
	} else static assert(A[$-1]~" not a defined class of 
"~this.stringof);

}


Re: Rebind template(bug?)

2016-08-21 Thread Engine Machine via Digitalmars-d-learn

On Monday, 22 August 2016 at 00:22:48 UTC, ag0aep6g wrote:

On 08/22/2016 12:06 AM, Engine Machine wrote:

T!()'s "data" is specified in the class just like all the other
derivations. I don't want to have to specify an external base 
class as
in your InstaniateOrBase. Why? Because!!! (There should be no 
need to,
and if one goes this route of creating classes, it should be 
all or

nothing, else there is no real benefit)


You make it sound like I came up with the external base class, 
but I just took that from your code.


No, what I meant was I don't want a base. I only added it in my 
code so it would compile/do what I want.



[...]
It seems that when one uses `class T(A...) : X`, one can't, 
for some X,
not have inheritance. The compiler expects X to be something 
inheritable

from no matter what.


I didn't know it, but your code shows that X can also be an 
empty compile time list (Seq). I have no idea if this is in the 
spec, or if it just happens to work with dmd.


If it's valid D, you just need a template that goes from T and 
A to T!(A[0 .. $ - 1]), or if A is already empty, to the empty 
Seq.


Like so:


template InstantiateOrEmptySeq(alias tmpl, args...)
{
alias Seq(T...)=T;
static if (args.length > 0)
alias InstantiateOrEmptySeq = tmpl!(args[0 .. $ - 1]);
else
alias InstantiateOrEmptySeq = Seq!();
}

class T(A...) : InstantiateOrEmptySeq!(T, A)
{
...
}



Yes! I though I tried that from Timon's original solution.

The following code works and does what I want!

template InstantiateOrEmptySeq(alias tmpl, args...)
{
alias Seq(T...)=T;
static if (args.length > 0)
alias InstantiateOrEmptySeq = tmpl!(args[0 .. $-1]);
else
alias InstantiateOrEmptySeq = Seq!();
}


class T(A...) : InstantiateOrEmptySeq!(T, A)
{   
static if (A.length == 0)
{
// Base class
int x;
} else  
static if (A[$-1] == "Animal")
{
int y;
} else
static if (A[$-1] == "Dog")
{
int z;
} else
static if (A[$-1] == "Pug")
{
int s;
	} else static assert(A[$-1]~" not a defined class of 
"~this.stringof);

}

The only down side is that the static if's are flat. They don't 
show the relationship between, say, Dog an Animal, that a nested 
set of static if's would show, but I think this is not possible 
due to the recursion and shadowing(I imagine one could test if 
the variables exist but that is messy).


Anyways, Thanks for the help.

I think this is just Timons answer anyways. What the original 
confusion was, was the shadowing, which I thought would not 
happen(or at least expected an error), Lodovico solved that.







Re: Rebind template(bug?)

2016-08-21 Thread ag0aep6g via Digitalmars-d-learn

On 08/22/2016 12:06 AM, Engine Machine wrote:

T!()'s "data" is specified in the class just like all the other
derivations. I don't want to have to specify an external base class as
in your InstaniateOrBase. Why? Because!!! (There should be no need to,
and if one goes this route of creating classes, it should be all or
nothing, else there is no real benefit)


You make it sound like I came up with the external base class, but I 
just took that from your code.


[...]

It seems that when one uses `class T(A...) : X`, one can't, for some X,
not have inheritance. The compiler expects X to be something inheritable
from no matter what.


I didn't know it, but your code shows that X can also be an empty 
compile time list (Seq). I have no idea if this is in the spec, or if it 
just happens to work with dmd.


If it's valid D, you just need a template that goes from T and A to 
T!(A[0 .. $ - 1]), or if A is already empty, to the empty Seq.


Like so:


template InstantiateOrEmptySeq(alias tmpl, args...)
{
alias Seq(T...)=T;
static if (args.length > 0)
alias InstantiateOrEmptySeq = tmpl!(args[0 .. $ - 1]);
else
alias InstantiateOrEmptySeq = Seq!();
}

class T(A...) : InstantiateOrEmptySeq!(T, A)
{
...
}





Re: Rebind template(bug?)

2016-08-21 Thread Engine Machine via Digitalmars-d-learn

On Sunday, 21 August 2016 at 21:11:37 UTC, ag0aep6g wrote:

On 08/21/2016 09:29 PM, Engine Machine wrote:
I know you like to play the right or wrong game, but did you 
ever learn

that a single example does not prove the truth of something?


But you can show in a single example that something doesn't 
work. You tried to do that, and you did it with a simple 
example, which is always appreciated. But apparently, you were 
wrong. Happens to the best. And when the compiler prints 
"tmpl!a" that's indeed a little misleading.


You being wrong there doesn't mean that the Rebind template as 
I posted it works correctly, of course. But Jack didn't claim 
that. He just said that your example for how it doesn't work is 
wrong. And as far as I see, Rebind does work as expected. But I 
wouldn't be surprised if there is some edge case where things 
fall apart.


Also, if you're looking for help or civil discussion, I suggest 
you try a less antagonistic approach. Things like "I know you 
like to [play games]" and "did you ever learn [whatever]" do 
not set the tone for that.



How about something more complex?

import std.stdio;
import std.meta, std.traits;

class base { }


Style nitpick: Class names in PascalCase, please.


template Rebind(alias instance, newArgs...)
{
import std.traits: TemplateOf;
alias tmpl = TemplateOf!instance;
static if (newArgs.length > 0)
alias Rebind = tmpl!newArgs;
else
alias Rebind = base;
}

template EraseLast(A...)
{
static if (A.length > 0)
alias EraseLast = Erase!(A[$-1], A);


This line can be simplified: alias EraseLast = A[0 .. $ - 1];


else
alias EraseLast = base;


This is quite surprising for a template that's called 
"EraseLast". I renamed it to "EraseLastOrBase" for myself when 
looking at this.



}



class T(A...) : Rebind!(T!A, EraseLast!A)


The core idea of Rebind isn't needed here, is it? You've got T, 
so you can just pass it directly. No need to extract it from 
T!A.


So, instead of using some form of Rebind, you can use a simpler 
template:



/* Instantiates tmpl with args, or if no args given, returns 
base. */

template InstantiateOrBase(alias tmpl, args ...)
{
static if (args.length == 0) alias InstantiateOrBase = base;
else alias InstantiateOrBase = tmpl!args;
}

class T(A...) : InstantiateOrBase!(T, EraseLast!A)



{
int x;


Note that this means that every instantiation of T brings its 
own x. That is, T!foo declares an x, and T!(foo, bar) which 
inherits from T!foo adds another x. The same happens with y, z, 
and s, of course.



static if (A.length > 0 && A[0] == "Animal")
{
int y;
static if (A.length > 1 && A[1] == "Dog")
{
int z;
static if (A.length > 2 && A[2] == "Pug")
int s;
}

}
}


pragma(msg, is(T!("Animal", "Dog", "Pug") : T!("Animal", 
"Dog")));

pragma(msg, is(T!("Animal", "Dog", "Pug") : T!("Animal")));
pragma(msg, is(T!("Animal", "Dog", "Pug") : base));
pragma(msg, is(T!("Animal", "Dog") : T!("Animal")));
pragma(msg, is(T!("Animal", "Dog") : base));
pragma(msg, is(T!("Animal") : base));


Asserts are great to show that something holds. When someone 
like me makes changes to your code in order to understand it, 
the complier throws a nice loud error in their face when they 
mess up. So I changed these to static asserts for myself.



// all true



void main()
{
auto t = new T!("Animal", "Dog", "Pug")();
T!("Animal", "Dog") q = t;
//T!("Animal", "Dog", "Pug") q = t; works but then q 
is not the

super of t
t.x = 3;
t.y = 4;
t.z = 6;
t.s = 123;

q.y = 1;
writeln(t, ", ", typeof(t).stringof);
writeln(q, ", ", typeof(q).stringof);
writeln("---");
writeln(t.x);
writeln(t.y);
writeln(t.z);
writeln(t.s);
writeln("---");
writeln(q.x);
writeln(q.y);
writeln(q.z);
writeln("---");
writeln(t.y);
writeln("---");
writeln(&t);
writeln(&q);

}

Since the pragma's are true, it is obvious that the 
inheritance should
work chain works. Yet q is not a reference to t as it should 
be, why is

this?


It would help a lot if you would point out what parts of the 
output are surprising to you. If you let the reader figure it 
out themselves, chances are 1) people are not going to bother, 
and 2) if they do bother, they might miss your point.


Labeling the output also helps. By that I mean, if you writ

Re: Rebind template(bug?)

2016-08-21 Thread ag0aep6g via Digitalmars-d-learn

On 08/21/2016 09:29 PM, Engine Machine wrote:

I know you like to play the right or wrong game, but did you ever learn
that a single example does not prove the truth of something?


But you can show in a single example that something doesn't work. You 
tried to do that, and you did it with a simple example, which is always 
appreciated. But apparently, you were wrong. Happens to the best. And 
when the compiler prints "tmpl!a" that's indeed a little misleading.


You being wrong there doesn't mean that the Rebind template as I posted 
it works correctly, of course. But Jack didn't claim that. He just said 
that your example for how it doesn't work is wrong. And as far as I see, 
Rebind does work as expected. But I wouldn't be surprised if there is 
some edge case where things fall apart.


Also, if you're looking for help or civil discussion, I suggest you try 
a less antagonistic approach. Things like "I know you like to [play 
games]" and "did you ever learn [whatever]" do not set the tone for that.



How about something more complex?

import std.stdio;
import std.meta, std.traits;

class base { }


Style nitpick: Class names in PascalCase, please.


template Rebind(alias instance, newArgs...)
{
import std.traits: TemplateOf;
alias tmpl = TemplateOf!instance;
static if (newArgs.length > 0)
alias Rebind = tmpl!newArgs;
else
alias Rebind = base;
}

template EraseLast(A...)
{
static if (A.length > 0)
alias EraseLast = Erase!(A[$-1], A);


This line can be simplified: alias EraseLast = A[0 .. $ - 1];


else
alias EraseLast = base;


This is quite surprising for a template that's called "EraseLast". I 
renamed it to "EraseLastOrBase" for myself when looking at this.



}



class T(A...) : Rebind!(T!A, EraseLast!A)


The core idea of Rebind isn't needed here, is it? You've got T, so you 
can just pass it directly. No need to extract it from T!A.


So, instead of using some form of Rebind, you can use a simpler template:


/* Instantiates tmpl with args, or if no args given, returns base. */
template InstantiateOrBase(alias tmpl, args ...)
{
static if (args.length == 0) alias InstantiateOrBase = base;
else alias InstantiateOrBase = tmpl!args;
}

class T(A...) : InstantiateOrBase!(T, EraseLast!A)



{
int x;


Note that this means that every instantiation of T brings its own x. 
That is, T!foo declares an x, and T!(foo, bar) which inherits from T!foo 
adds another x. The same happens with y, z, and s, of course.



static if (A.length > 0 && A[0] == "Animal")
{
int y;
static if (A.length > 1 && A[1] == "Dog")
{
int z;
static if (A.length > 2 && A[2] == "Pug")
int s;
}

}
}


pragma(msg, is(T!("Animal", "Dog", "Pug") : T!("Animal", "Dog")));
pragma(msg, is(T!("Animal", "Dog", "Pug") : T!("Animal")));
pragma(msg, is(T!("Animal", "Dog", "Pug") : base));
pragma(msg, is(T!("Animal", "Dog") : T!("Animal")));
pragma(msg, is(T!("Animal", "Dog") : base));
pragma(msg, is(T!("Animal") : base));


Asserts are great to show that something holds. When someone like me 
makes changes to your code in order to understand it, the complier 
throws a nice loud error in their face when they mess up. So I changed 
these to static asserts for myself.



// all true



void main()
{
auto t = new T!("Animal", "Dog", "Pug")();
T!("Animal", "Dog") q = t;
//T!("Animal", "Dog", "Pug") q = t; works but then q is not the
super of t
t.x = 3;
t.y = 4;
t.z = 6;
t.s = 123;

q.y = 1;
writeln(t, ", ", typeof(t).stringof);
writeln(q, ", ", typeof(q).stringof);
writeln("---");
writeln(t.x);
writeln(t.y);
writeln(t.z);
writeln(t.s);
writeln("---");
writeln(q.x);
writeln(q.y);
writeln(q.z);
writeln("---");
writeln(t.y);
writeln("---");
writeln(&t);
writeln(&q);

}

Since the pragma's are true, it is obvious that the inheritance should
work chain works. Yet q is not a reference to t as it should be, why is
this?


It would help a lot if you would point out what parts of the output are 
surprising to you. If you let the reader figure it out themselves, 
chances are 1) people are not going to bother, and 2) if they do bother, 
they might miss your point.


Labeling the output also helps. By that I mean, if you write 
`writeln("t.x: ", t.x);`, the output can be read much more easily. I 
al

Re: Rebind template(bug?)

2016-08-21 Thread Lodovico Giaretta via Digitalmars-d-learn

On Sunday, 21 August 2016 at 20:36:54 UTC, Engine Machine wrote:
On Sunday, 21 August 2016 at 19:42:08 UTC, Lodovico Giaretta 
wrote:

[...]


You're right. I didn't realize that variables could be shadowed 
in classes. Seems dangerous. D doesn't allow shadowing in a 
normal context and gives an error so I don't know why it 
wouldn't do that in classes. (since it wasn't giving an error I 
thought it wasn't shadowing)


You are right. It is very bad. But as far as I know Java and C++ 
allow this too.
I will open an enhancement request (if there's none about this), 
to gather some feedback on the matter.


Re: Rebind template(bug?)

2016-08-21 Thread Engine Machine via Digitalmars-d-learn
On Sunday, 21 August 2016 at 19:42:08 UTC, Lodovico Giaretta 
wrote:

On Sunday, 21 August 2016 at 19:29:26 UTC, Engine Machine wrote:

[...]


The problem of this code has nothing to do with aliases. They 
work correctly. The problem is variable shadowing. In the 
following code, Child has two x variables, one of which is only 
accessible from a Parent reference, the other only from a Child 
reference.


class Parent
{
int x;
}
class Child: Parent
{
int x; // this shadows Parent.x
int y;
}

void main()
{
Child child = new Child();
Parent parent = child;

child.x = child.y = 3;
parent.x = 2;

assert(child.x == 3);
assert((cast(Child)parent).x == 3);
assert((cast(Parent)child).x == 2);

assert(parent is child); // same object (remember that a 
class is already a pointer);
assert(&parent != &child); // but there are two different 
pointers on the stack (pointing to the same object)

}


You're right. I didn't realize that variables could be shadowed 
in classes. Seems dangerous. D doesn't allow shadowing in a 
normal context and gives an error so I don't know why it wouldn't 
do that in classes. (since it wasn't giving an error I thought it 
wasn't shadowing)







Re: Rebind template(bug?)

2016-08-21 Thread Jack Applegame via Digitalmars-d-learn

On Sunday, 21 August 2016 at 19:29:26 UTC, Engine Machine wrote:
I know you like to play the right or wrong game, but did you 
ever learn that a single example does not prove the truth of 
something?


How about something more complex?
Your demagogy will not help you learn the basics of the D 
language. And you're wrong again, young arrogant padawan.


Re: Rebind template

2016-08-21 Thread Alexandru Ermicioi via Digitalmars-d-learn

On Saturday, 20 August 2016 at 22:18:57 UTC, Engine Machine wrote:
On Saturday, 20 August 2016 at 22:11:40 UTC, Engine Machine 
wrote:

Is there a way to rebind the arguments of a template?

template foo(X)
{
   // X is like A!(a,b,c)
   Y = Rebind!(X,d,e,f);
   // Y is like A!(d,e,f);
}

foo(A!(a,b,c));

?


I'd also be happy if I could just remove the last element from 
A.


template EraseLast(X)
{
// returns A!(a,b) when X = A!(a,b,c)
}


Check for ApplyLeft and ApplyRight in std.meta, maybe it can help 
you.


http://dlang.org/phobos/std_meta.html#.ApplyLeft
http://dlang.org/phobos/std_meta.html#.ApplyRight


Re: Rebind template(bug?)

2016-08-21 Thread Lodovico Giaretta via Digitalmars-d-learn
On Sunday, 21 August 2016 at 19:42:08 UTC, Lodovico Giaretta 
wrote:

On Sunday, 21 August 2016 at 19:29:26 UTC, Engine Machine wrote:

[...]


The problem of this code has nothing to do with aliases. They 
work correctly. The problem is variable shadowing. In the 
following code, Child has two x variables, one of which is only 
accessible from a Parent reference, the other only from a Child 
reference.


class Parent
{
int x;
}
class Child: Parent
{
int x; // this shadows Parent.x
int y;
}

void main()
{
Child child = new Child();
Parent parent = child;

child.x = child.y = 3;
parent.x = 2;

assert(child.x == 3);
assert((cast(Child)parent).x == 3);
assert((cast(Parent)child).x == 2);

assert(parent is child); // same object (remember that a 
class is already a pointer);
assert(&parent != &child); // but there are two different 
pointers on the stack (pointing to the same object)

}


A patch to your code that makes it work, with the parts not 
displayed unchanged:


class base
{
int x;
}

class T(A...) : Rebind!(T!A, EraseLast!A)
{
static if(A[$-1] == "Animal")
int y;
else static if (A[$-1] == "Dog")
int z;
else static if (A[$-1] == "Pug")
int s;
}


Re: Rebind template(bug?)

2016-08-21 Thread Lodovico Giaretta via Digitalmars-d-learn

On Sunday, 21 August 2016 at 19:29:26 UTC, Engine Machine wrote:

[...]


The problem of this code has nothing to do with aliases. They 
work correctly. The problem is variable shadowing. In the 
following code, Child has two x variables, one of which is only 
accessible from a Parent reference, the other only from a Child 
reference.


class Parent
{
int x;
}
class Child: Parent
{
int x; // this shadows Parent.x
int y;
}

void main()
{
Child child = new Child();
Parent parent = child;

child.x = child.y = 3;
parent.x = 2;

assert(child.x == 3);
assert((cast(Child)parent).x == 3);
assert((cast(Parent)child).x == 2);

assert(parent is child); // same object (remember that a 
class is already a pointer);
assert(&parent != &child); // but there are two different 
pointers on the stack (pointing to the same object)

}



Re: Rebind template(bug?)

2016-08-21 Thread Engine Machine via Digitalmars-d-learn

On Sunday, 21 August 2016 at 06:28:25 UTC, Jack Applegame wrote:

On Sunday, 21 August 2016 at 00:06:07 UTC, Engine Machine wrote:

On Saturday, 20 August 2016 at 22:21:00 UTC, ag0aep6g wrote:

On 08/21/2016 12:11 AM, Engine Machine wrote:

Is there a way to rebind the arguments of a template?

template foo(X)
{
   // X is like A!(a,b,c)
   Y = Rebind!(X,d,e,f);
   // Y is like A!(d,e,f);
}

foo(A!(a,b,c));

?


template Rebind(alias instance, newArgs...)
{
import std.traits: TemplateOf;
alias tmpl = TemplateOf!instance;
alias Rebind = tmpl!newArgs;
}


This doesn't work because the rebound type is of type tmpl and 
not the original


e.g.,

Rebind!(T!b, a)

is tmpl!a not T!a.


You are wrong. tmpl is just alias of template T. So tmpl!a and 
T!a are the same type.


alias X = T!(int, short, char);
alias Y = Rebind!(X, short, char, int);
static assert(is(Y == T!(short, char, int))); // passes


I know you like to play the right or wrong game, but did you ever 
learn that a single example does not prove the truth of something?


How about something more complex?

import std.stdio;
import std.meta, std.traits;

class base { }

template Rebind(alias instance, newArgs...)
{
import std.traits: TemplateOf;
alias tmpl = TemplateOf!instance;
static if (newArgs.length > 0)
alias Rebind = tmpl!newArgs;
else
alias Rebind = base;
}

template EraseLast(A...)
{
static if (A.length > 0)
alias EraseLast = Erase!(A[$-1], A);
else
alias EraseLast = base;
}



class T(A...) : Rebind!(T!A, EraseLast!A)
{
int x;
static if (A.length > 0 && A[0] == "Animal")
{
int y;
static if (A.length > 1 && A[1] == "Dog")
{
int z;
static if (A.length > 2 && A[2] == "Pug")
int s;
}

}
}


pragma(msg, is(T!("Animal", "Dog", "Pug") : T!("Animal", "Dog")));
pragma(msg, is(T!("Animal", "Dog", "Pug") : T!("Animal")));
pragma(msg, is(T!("Animal", "Dog", "Pug") : base));
pragma(msg, is(T!("Animal", "Dog") : T!("Animal")));
pragma(msg, is(T!("Animal", "Dog") : base));
pragma(msg, is(T!("Animal") : base));

// all true



void main()
{
auto t = new T!("Animal", "Dog", "Pug")();
T!("Animal", "Dog") q = t;
//T!("Animal", "Dog", "Pug") q = t; works but then q is 
not the super of t

t.x = 3;
t.y = 4;
t.z = 6;
t.s = 123;

q.y = 1;
writeln(t, ", ", typeof(t).stringof);
writeln(q, ", ", typeof(q).stringof);
writeln("---");
writeln(t.x);
writeln(t.y);
writeln(t.z);
writeln(t.s);
writeln("---");
writeln(q.x);
writeln(q.y);
writeln(q.z);
writeln("---");
writeln(t.y);
writeln("---");
writeln(&t);
writeln(&q);

}

Since the pragma's are true, it is obvious that the inheritance 
should work chain works. Yet q is not a reference to t as it 
should be, why is this? If aliases were truly aliases as you 
think(your generic response) then it should work because rebind 
and erase only use aliases.













Re: Rebind template

2016-08-20 Thread Jack Applegame via Digitalmars-d-learn

On Sunday, 21 August 2016 at 00:06:07 UTC, Engine Machine wrote:

On Saturday, 20 August 2016 at 22:21:00 UTC, ag0aep6g wrote:

On 08/21/2016 12:11 AM, Engine Machine wrote:

Is there a way to rebind the arguments of a template?

template foo(X)
{
   // X is like A!(a,b,c)
   Y = Rebind!(X,d,e,f);
   // Y is like A!(d,e,f);
}

foo(A!(a,b,c));

?


template Rebind(alias instance, newArgs...)
{
import std.traits: TemplateOf;
alias tmpl = TemplateOf!instance;
alias Rebind = tmpl!newArgs;
}


This doesn't work because the rebound type is of type tmpl and 
not the original


e.g.,

Rebind!(T!b, a)

is tmpl!a not T!a.


You are wrong. tmpl is just alias of template T. So tmpl!a and 
T!a are the same type.


alias X = T!(int, short, char);
alias Y = Rebind!(X, short, char, int);
static assert(is(Y == T!(short, char, int))); // passes



Re: Rebind template

2016-08-20 Thread Engine Machine via Digitalmars-d-learn

On Saturday, 20 August 2016 at 22:21:00 UTC, ag0aep6g wrote:

On 08/21/2016 12:11 AM, Engine Machine wrote:

Is there a way to rebind the arguments of a template?

template foo(X)
{
   // X is like A!(a,b,c)
   Y = Rebind!(X,d,e,f);
   // Y is like A!(d,e,f);
}

foo(A!(a,b,c));

?


template Rebind(alias instance, newArgs...)
{
import std.traits: TemplateOf;
alias tmpl = TemplateOf!instance;
alias Rebind = tmpl!newArgs;
}


This doesn't work because the rebound type is of type tmpl and 
not the original


e.g.,

Rebind!(T!b, a)

is tmpl!a not T!a.



Re: Rebind template

2016-08-20 Thread ag0aep6g via Digitalmars-d-learn

On 08/21/2016 12:11 AM, Engine Machine wrote:

Is there a way to rebind the arguments of a template?

template foo(X)
{
   // X is like A!(a,b,c)
   Y = Rebind!(X,d,e,f);
   // Y is like A!(d,e,f);
}

foo(A!(a,b,c));

?


template Rebind(alias instance, newArgs...)
{
import std.traits: TemplateOf;
alias tmpl = TemplateOf!instance;
alias Rebind = tmpl!newArgs;
}


Re: Rebind template

2016-08-20 Thread Engine Machine via Digitalmars-d-learn

On Saturday, 20 August 2016 at 22:11:40 UTC, Engine Machine wrote:

Is there a way to rebind the arguments of a template?

template foo(X)
{
   // X is like A!(a,b,c)
   Y = Rebind!(X,d,e,f);
   // Y is like A!(d,e,f);
}

foo(A!(a,b,c));

?


I'd also be happy if I could just remove the last element from A.

template EraseLast(X)
{
// returns A!(a,b) when X = A!(a,b,c)
}


Rebind template

2016-08-20 Thread Engine Machine via Digitalmars-d-learn

Is there a way to rebind the arguments of a template?

template foo(X)
{
   // X is like A!(a,b,c)
   Y = Rebind!(X,d,e,f);
   // Y is like A!(d,e,f);
}

foo(A!(a,b,c));

?