Re: How about a special null template parameter?

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

On Monday, 22 August 2016 at 15:58:14 UTC, Meta wrote:

On Sunday, 21 August 2016 at 21:21:22 UTC, Engine Machine wrote:
Well, I see that a template with 0 parameters can act as a 
"type", if you will.


Just like functions

void foo(T)(T x)

acts like a normal function foo(3) even though it is a 
templated function.


In fact, I see very little difference between a template with 
0 parameters and a type.


Type!() = Type


I think this is a very bad idea theory-wise, if not in practice 
as well. A template is a type constructor, not a type. They are 
two very different things. You can get the size of a type, its 
members, etc. while you cannot for a template.


Yeah, maybe... but I think this is a user issue and not a 
language issue.  The programmer should attempt to know what he is 
doing. I'd prefer to use an extended ascii syntax so we can have 
proper categorization of things.


e.g.,
æType - a type
½Template - a template

Or whatever.

That way it is very easy to know what is what ;) Symbols may 
vary...




Re: How about a special null template parameter?

2016-08-22 Thread Meta via Digitalmars-d

On Sunday, 21 August 2016 at 21:21:22 UTC, Engine Machine wrote:
Well, I see that a template with 0 parameters can act as a 
"type", if you will.


Just like functions

void foo(T)(T x)

acts like a normal function foo(3) even though it is a 
templated function.


In fact, I see very little difference between a template with 0 
parameters and a type.


Type!() = Type


I think this is a very bad idea theory-wise, if not in practice 
as well. A template is a type constructor, not a type. They are 
two very different things. You can get the size of a type, its 
members, etc. while you cannot for a template.





Re: How about a special null template parameter?

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

On Sunday, 21 August 2016 at 00:44:01 UTC, Timon Gehr wrote:

On 20.08.2016 21:20, Engine Machine wrote:


That is

It would be nice to have something like

alias Type = Type!();
class Type(T...): TypeParent!T if(T.length==1){
int x;
static if (T is Dog)
int y;
}


I don't understand how this is related.



The only difference is the alias Type = Type!(); Again, D 
can't do this
but the point is that it would be nice to have the alias. One 
can't do

everything as a "library" solution.
...


I see what you are after (but this was not part of the original 
requirements :)   ). I don't think there's a way to make a 
symbol act as both a type and a template.


Well, I see that a template with 0 parameters can act as a 
"type", if you will.


Just like functions

void foo(T)(T x)

acts like a normal function foo(3) even though it is a templated 
function.


In fact, I see very little difference between a template with 0 
parameters and a type.


Type!() = Type

seems very natural an logical to me as long as Type isn't defined 
anywhere else... but that is a problem in all cases(e.g., even 
functions).


Maybe there is some good reason though that simplifies the 
compiler.





Trying to expand your code results in some odd behavior:


public template TypeParent(P)
{
import std.traits;
alias T = TemplateArgsOf!P;
alias Seq(T...) = T;
static if (T.length == 0 || is(typeof(T[0]) == 
typeof(null)))

{
alias TypeParent = Seq!();
}
else
{
alias TypeParent = Seq!(P!(T[0..T.length-1]));
}
}


class Type(T...) : TypeParent!(Type!T)
{
int x;
static if (T.length >= 1 && T[0] is "Animal")
{
int y;
static if (T.length >= 2 && T[1] is "Dog")
{
int z;
static if (T.length >= 3&& T[2] is "Pug")
{
int s;
}
}

}
}


void main()
{

import std.traits;

auto a = new Type!("Animal", "Dog", "Pug")();
Type!("Animal", "Dog") b = a;
Type!("Animal") c = b;

a.s = 1;
b.z = 2;
c.y = 3;
}

b and c are of type P!, not Type!


It seems that this is a compiler bug. Is the problem just with 
getting a string representation of the type?


I think it is just that D isn't "unaliasing" the template 
parameter, P in this case, to what it aliases... It makes it seem 
like things are different. Why one would have to keep track of 
internal template aliases is beyond me. D should rewrite the 
internal parameters in to meaningful external scope parameters if 
possible(which should be possible since it must know the input to 
the template).





Re: How about a special null template parameter?

2016-08-20 Thread Timon Gehr via Digitalmars-d

On 20.08.2016 21:20, Engine Machine wrote:


That is

It would be nice to have something like

alias Type = Type!();
class Type(T...): TypeParent!T if(T.length==1){
int x;
static if (T is Dog)
int y;
}


I don't understand how this is related.



The only difference is the alias Type = Type!(); Again, D can't do this
but the point is that it would be nice to have the alias. One can't do
everything as a "library" solution.
...


I see what you are after (but this was not part of the original 
requirements :)   ). I don't think there's a way to make a symbol act as 
both a type and a template.




Trying to expand your code results in some odd behavior:


public template TypeParent(P)
{
import std.traits;
alias T = TemplateArgsOf!P;
alias Seq(T...) = T;
static if (T.length == 0 || is(typeof(T[0]) == typeof(null)))
{
alias TypeParent = Seq!();
}
else
{
alias TypeParent = Seq!(P!(T[0..T.length-1]));
}
}


class Type(T...) : TypeParent!(Type!T)
{
int x;
static if (T.length >= 1 && T[0] is "Animal")
{
int y;
static if (T.length >= 2 && T[1] is "Dog")
{
int z;
static if (T.length >= 3&& T[2] is "Pug")
{
int s;
}
}

}
}


void main()
{

import std.traits;

auto a = new Type!("Animal", "Dog", "Pug")();
Type!("Animal", "Dog") b = a;
Type!("Animal") c = b;

a.s = 1;
b.z = 2;
c.y = 3;
}

b and c are of type P!, not Type!


It seems that this is a compiler bug. Is the problem just with getting a 
string representation of the type?


Re: How about a special null template parameter?

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

On Saturday, 20 August 2016 at 10:04:07 UTC, Timon Gehr wrote:

On 20.08.2016 00:07, Engine Machine wrote:

On Friday, 19 August 2016 at 21:07:42 UTC, Timon Gehr wrote:

On 19.08.2016 20:25, Engine Machine wrote:

So we can create types relationships easier:

class Type(T) : Type!null
{
   int x;
   static if (T is Dog)
   int y;



alias Seq(T...)=T;

template TypeParent(T...) if(T.length==1){
static if(is(typeof(T[0])==typeof(null))) alias 
TypeParent = Seq!();

else alias TypeParent = Seq!(Type!null);
}

class Type(T...): TypeParent!T if(T.length==1){
   int x;
   static if (T is Dog)
   int y;
}


This is a bit verbose


Apart from the workaround for the ridiculous alias template 
parameter semantics, I think the length of the code more or 
less matches the specificity of the requested behaviour. (There 
should be ways to abstract out most of it, in case you need 
this really often.)


Yes, it is not too bad. One doesn't need to T.length part so it 
is a little shorter. Took me a bit to get used to it.






and not quite right (T is Dog should be something
like T[0], or whatever).
...


('T is Dog' does not work anyway.)



Yes, I use strings, but it doesn't really matter, it can be made 
to work.




It does essentially work. My only complaint is that it would 
be nice to
be able to export an alias to Type!() = Type; in the namespace 
of the
type being created. Doubt that D can do that!? If it can, then 
it should

be an adequate solution.

That is

It would be nice to have something like

alias Type = Type!();
class Type(T...): TypeParent!T if(T.length==1){
int x;
static if (T is Dog)
int y;
}


I don't understand how this is related.



The only difference is the alias Type = Type!(); Again, D can't 
do this but the point is that it would be nice to have the alias. 
One can't do everything as a "library" solution.


Trying to expand your code results in some odd behavior:


public template TypeParent(P)
{   
import std.traits;
alias T = TemplateArgsOf!P;
alias Seq(T...) = T;
static if (T.length == 0 || is(typeof(T[0]) == typeof(null)))
{
alias TypeParent = Seq!();  
}
else
{
alias TypeParent = Seq!(P!(T[0..T.length-1]));
}
}


class Type(T...) : TypeParent!(Type!T)
{
int x;
static if (T.length >= 1 && T[0] is "Animal")
{
int y;
static if (T.length >= 2 && T[1] is "Dog")
{
int z;
static if (T.length >= 3&& T[2] is "Pug")
{
int s;
}
}

}
}


void main()
{

import std.traits;

auto a = new Type!("Animal", "Dog", "Pug")();
Type!("Animal", "Dog") b = a;   
Type!("Animal") c = b;

a.s = 1;
b.z = 2;
c.y = 3;
}

b and c are of type P!, not Type!


Re: How about a special null template parameter?

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

On Saturday, 20 August 2016 at 13:45:59 UTC, poliklosio wrote:

On Friday, 19 August 2016 at 18:25:06 UTC, Engine Machine wrote:

So we can create types relationships easier:

class Type(T) : Type!null
{
   int x;
   static if (T is Dog)
   int y;
}

Type == Type!null (!null implicit, only if defined in the 
above way. Essentially an alias is created for us 
automatically)


This syntax would be very confusing to a non-expert. It is a 
special case of an existing features (inheritance and 
templates), which makes it hard to learn about, as all 
resources are going to discuss those other features first, and 
only the most detailed readings are going to contain this 
detail. Moreover, it does not introduce a keyword or any other 
name, so it is almost impossible to Google. Try googling 
something like "template class a class b: public 
a", and see which result contains "curiously recurring 
template pattern". It is hard to find, isn't it?


Moreover, as indicated by another poster, null is already a 
valid template parameter, making it even more confusing. Also 
it is unclear when the interpretation would be as you propose.


You need to appreciate the difference between write-only code 
and code that can be easily read, reviewed and understood.


Dlang has already went too far in inventing pieces of 
non-obvious syntax for template features. Lets not make the 
situation worse.


Distill what you want to do, see what use cases are covered by 
other features and libraries, name your thing accordingly and 
then propose.


Do you not realize that if every human endeavor was to bow down 
to the lowest common denominator there would be no point?


If Walter had the notion "I have to make D so the beginner can 
understand it easily" Then D would be javascript or php?


If you want to be an idiot and use an idiot language, then there 
are many out there. Go program in BASIC.


So your arguments appealing to ignorance(not the logical fallacy, 
of course) is non-sense.  Life is complex, stop trying to reduce 
it to something you already can understand. I think, technically, 
this is called laziness.









Re: How about a special null template parameter?

2016-08-20 Thread poliklosio via Digitalmars-d

On Friday, 19 August 2016 at 18:25:06 UTC, Engine Machine wrote:

So we can create types relationships easier:

class Type(T) : Type!null
{
   int x;
   static if (T is Dog)
   int y;
}

Type == Type!null (!null implicit, only if defined in the above 
way. Essentially an alias is created for us automatically)


This syntax would be very confusing to a non-expert. It is a 
special case of an existing features (inheritance and templates), 
which makes it hard to learn about, as all resources are going to 
discuss those other features first, and only the most detailed 
readings are going to contain this detail. Moreover, it does not 
introduce a keyword or any other name, so it is almost impossible 
to Google. Try googling something like "template class a 
class b: public a", and see which result contains "curiously 
recurring template pattern". It is hard to find, isn't it?


Moreover, as indicated by another poster, null is already a valid 
template parameter, making it even more confusing. Also it is 
unclear when the interpretation would be as you propose.


You need to appreciate the difference between write-only code and 
code that can be easily read, reviewed and understood.


Dlang has already went too far in inventing pieces of non-obvious 
syntax for template features. Lets not make the situation worse.


Distill what you want to do, see what use cases are covered by 
other features and libraries, name your thing accordingly and 
then propose.


Re: How about a special null template parameter?

2016-08-20 Thread Timon Gehr via Digitalmars-d

On 20.08.2016 00:07, Engine Machine wrote:

On Friday, 19 August 2016 at 21:07:42 UTC, Timon Gehr wrote:

On 19.08.2016 20:25, Engine Machine wrote:

So we can create types relationships easier:

class Type(T) : Type!null
{
   int x;
   static if (T is Dog)
   int y;



alias Seq(T...)=T;

template TypeParent(T...) if(T.length==1){
static if(is(typeof(T[0])==typeof(null))) alias TypeParent = Seq!();
else alias TypeParent = Seq!(Type!null);
}

class Type(T...): TypeParent!T if(T.length==1){
   int x;
   static if (T is Dog)
   int y;
}


This is a bit verbose


Apart from the workaround for the ridiculous alias template parameter 
semantics, I think the length of the code more or less matches the 
specificity of the requested behaviour. (There should be ways to 
abstract out most of it, in case you need this really often.)



and not quite right (T is Dog should be something
like T[0], or whatever).
...


('T is Dog' does not work anyway.)


It does essentially work. My only complaint is that it would be nice to
be able to export an alias to Type!() = Type; in the namespace of the
type being created. Doubt that D can do that!? If it can, then it should
be an adequate solution.

That is

It would be nice to have something like

alias Type = Type!();
class Type(T...): TypeParent!T if(T.length==1){
int x;
static if (T is Dog)
int y;
}


I don't understand how this is related.


Re: How about a special null template parameter?

2016-08-19 Thread Chris Wright via Digitalmars-d
On Fri, 19 Aug 2016 23:43:05 +, Engine Machine wrote:
> then the only question is can the current compiler interpret ^n
> unambiguously and without undue complexity. If it can, and such a
> syntactic rewrite is useful, then it should be implemented.

No. You must weigh the added complexity against the benefits. The less 
frequently a feature will be used, the more surprise you will inflict on 
people when they encounter it. The less like other things in the language 
this new feature is, the more awkward it will be for users.

You called your suggestion "syntactic sugar", but if we can call it that, 
we can say the same of templates. Your implication that it is a simple 
change is incorrect.

Your proposal clashes with existing features. It's even a breaking 
change. It's implemented easily enough by hand with:

class SomeFoo {
  // common fields and methods, possibly abstract
}

class Foo(T) : SomeFoo {
  // everything else
}

The by-hand implementation is also more obvious.

You would have to change the proposed syntax, show that this can't be 
reasonably done in a library, and show what it gives you that's 
appreciably better than what's currently there.


Re: How about a special null template parameter?

2016-08-19 Thread Engine Machine via Digitalmars-d
On Friday, 19 August 2016 at 22:20:29 UTC, Lodovico Giaretta 
wrote:

On Friday, 19 August 2016 at 21:51:38 UTC, Engine Machine wrote:
On Friday, 19 August 2016 at 19:19:35 UTC, Lodovico Giaretta 
wrote:
1) `null` has a very precise meaning: it is the only valid 
value of an unnamed type only known as `typeof(null)`, which 
implicitly converts to any class/pointer/dynamic 
array/associative array type. Thus this thing should have a 
different name.


null as many interpretations. It is ok to expand the meaning. 
It is done all the time. If it confuses you are creates a 
semantic difficulty, I don't mind what it is called. It could 
be called Boomfurkasufasdf.


In this case, defining it to be null fits in semantically 
though. If it creates some compiler issue then, again, 
anything else could be used. I'd prefer Null or NULL or Aleph 
or something short and meaningless.


The problem is that null is a valid value to instantiate an 
alias template parameter with. So using it to do something 
completely different may create ambiguity (does that null means 
"parent template" or is it a valid instantiation? Who knows). 
But as you said, this is just a matter of finding a name.




Yes, but in this case it is used in a very specific and exact 
sense, so it is not arbitrarily ambiguous. Again, if it is, then 
just use some other syntax.





2) What about this case:
```
class Type(T): Type
{
static if (T is Dog)
int y;
else
float z;
}
```
What should be inside the base?


z.


This is wrong. If Type has to be the base class of every 
Type!T, then it cannot contain z, as there is one Type!T 
(namely Type!Dog) which does not contain z. So in this case the 
base class Type should be empty. As you see it is not that 
simple.


Yeah, T should be empty. This is not a good example though 
because one wouldn't compose such things like this. It is quite 
simple when one follows the logical guidelines. The code would 
"work" but the inheritance hierarchy would not be correct and the 
compiler would spit out errors, as it should.


So, even if I mis-reasoned about it(quickly glanced over it 
without thinking), it doesn't change anything though.


Base would be empty and technically we would have two types of 
derived types. One of Dog with y in it and everything else with z 
in it, call it E.


Dog and E would just be derived types of Type.

It is no different than

class Type(T): Type
{
   static if (T is Dog)
int y;
   else static if (T !is Dog)
float z;
}


which is semantically equivalent to

class Type(T): Type
{
   static if (T is Dog)
int y;
   else static if (T is E)
float z;
}

Where E is everything that is not a Dog.



4) I think that the value of this addition is little wrt. the 
amount of work the compiler should do to implement it (which 
at first sight would be a lot). But this is of course just my 
opinion.


It is just syntactic sugar and requires no complex compiler 
modifications. The benefit is reduced visual complexity and 
that is always a bonus. That is the point we don't write in 
0's and 1's... everything else is just syntactic sugar. In 
this case, it is a very simple rewrite rule. A few lines of 
code would be all that is required.


I'm not an expert, but I think this requires *a lot* of 
compiler work: it has to analyze every symbol in the class to 
find out whether it must be part of the "uninstantiated" base 
or not. And this kind of analysis may not be easy (it may be 
masked by the use of traits, template mixins, string mixins and 
so on). Even humans can easily get it wrong (see my previous 
example).


Yes, it might. But if it is truly just semantic sugar, then it 
shouldn't pose any problem because it's just a rewrite. Obviously 
I am not suggesting it just be written up in a New York minute 
and thrown in the code. It needs to be properly analyzed and such.





Also, I thought of other problems:
- Interaction with non-class templates: how should they behave? 
Or are we just introducing a special case for class templates? 
(Special cases are very bad, we should limit them).
- Interaction with base classes and interfaces: how is this 
"uninstantiated base class" inserted into the graph of classes 
and interfaces? Are interfaces considered implemented by this 
base class? Is this base class inserted between the templated 
class and the "original" base class?


I think you are making it too complicated. This is a grammar 
transformation. If the syntax is grammatically equivalent to 
something already implementable in the language, then one only 
has to make sure the new syntactic sugar does not collide with 
pre-existing semantic evaluations.


Basically, if the compiler can always transform it in to valid 
code and the new syntax doesn't create ambiguous or wrong 
interpretations, then it is valid.


Since I've already said that basically it is a simplification of 
the type system for classes, and have hinted at the rewrite 

Re: How about a special null template parameter?

2016-08-19 Thread Enamex via Digitalmars-d

On Friday, 19 August 2016 at 23:12:39 UTC, Engine Machine wrote:

On Friday, 19 August 2016 at 22:20:09 UTC, Enamex wrote:
On Friday, 19 August 2016 at 18:25:06 UTC, Engine Machine 
wrote:

[...]


Something like this:

class Type(T: typeof(null)) { //< L1 (specialization)
int x;
}

class Dog {}

class Type(T) : Type!(typeof(null)) { //< L2 (`typeof(null)`)
static if(is(T: Dog)) //< L3 (`is(MyType: IntendedType)` 
or `is(MyType == ExactType)`)

int y;
}

What you're looking for is "specialization", on line "L1". 
Also some corrections on lines "L2" and "L3"


How is this any different, besides adding meaningless 
complexity, to inheritence as it already is?


Um, not sure what you mean. This isn't suggesting adding 
anything; it's already legal/compiles.


Re: How about a special null template parameter?

2016-08-19 Thread Engine Machine via Digitalmars-d

On Friday, 19 August 2016 at 22:20:09 UTC, Enamex wrote:

On Friday, 19 August 2016 at 18:25:06 UTC, Engine Machine wrote:

[...]


Something like this:

class Type(T: typeof(null)) { //< L1 (specialization)
int x;
}

class Dog {}

class Type(T) : Type!(typeof(null)) { //< L2 (`typeof(null)`)
static if(is(T: Dog)) //< L3 (`is(MyType: IntendedType)` or 
`is(MyType == ExactType)`)

int y;
}

What you're looking for is "specialization", on line "L1". Also 
some corrections on lines "L2" and "L3"


How is this any different, besides adding meaningless complexity, 
to inheritence as it already is?


Re: How about a special null template parameter?

2016-08-19 Thread Lodovico Giaretta via Digitalmars-d

On Friday, 19 August 2016 at 21:51:38 UTC, Engine Machine wrote:
On Friday, 19 August 2016 at 19:19:35 UTC, Lodovico Giaretta 
wrote:
1) `null` has a very precise meaning: it is the only valid 
value of an unnamed type only known as `typeof(null)`, which 
implicitly converts to any class/pointer/dynamic 
array/associative array type. Thus this thing should have a 
different name.


null as many interpretations. It is ok to expand the meaning. 
It is done all the time. If it confuses you are creates a 
semantic difficulty, I don't mind what it is called. It could 
be called Boomfurkasufasdf.


In this case, defining it to be null fits in semantically 
though. If it creates some compiler issue then, again, anything 
else could be used. I'd prefer Null or NULL or Aleph or 
something short and meaningless.


The problem is that null is a valid value to instantiate an alias 
template parameter with. So using it to do something completely 
different may create ambiguity (does that null means "parent 
template" or is it a valid instantiation? Who knows). But as you 
said, this is just a matter of finding a name.




2) What about this case:
```
class Type(T): Type
{
static if (T is Dog)
int y;
else
float z;
}
```
What should be inside the base?


z.


This is wrong. If Type has to be the base class of every Type!T, 
then it cannot contain z, as there is one Type!T (namely 
Type!Dog) which does not contain z. So in this case the base 
class Type should be empty. As you see it is not that simple.



I am after simplifying class design.


Fair enough. Though I'm not sure this is the right way to go.

4) I think that the value of this addition is little wrt. the 
amount of work the compiler should do to implement it (which 
at first sight would be a lot). But this is of course just my 
opinion.


It is just syntactic sugar and requires no complex compiler 
modifications. The benefit is reduced visual complexity and 
that is always a bonus. That is the point we don't write in 0's 
and 1's... everything else is just syntactic sugar. In this 
case, it is a very simple rewrite rule. A few lines of code 
would be all that is required.


I'm not an expert, but I think this requires *a lot* of compiler 
work: it has to analyze every symbol in the class to find out 
whether it must be part of the "uninstantiated" base or not. And 
this kind of analysis may not be easy (it may be masked by the 
use of traits, template mixins, string mixins and so on). Even 
humans can easily get it wrong (see my previous example).


Also, I thought of other problems:
- Interaction with non-class templates: how should they behave? 
Or are we just introducing a special case for class templates? 
(Special cases are very bad, we should limit them).
- Interaction with base classes and interfaces: how is this 
"uninstantiated base class" inserted into the graph of classes 
and interfaces? Are interfaces considered implemented by this 
base class? Is this base class inserted between the templated 
class and the "original" base class?


Re: How about a special null template parameter?

2016-08-19 Thread Enamex via Digitalmars-d

On Friday, 19 August 2016 at 18:25:06 UTC, Engine Machine wrote:

So we can create types relationships easier:

class Type(T) : Type!null
{
   int x;
   static if (T is Dog)
   int y;
}

Type == Type!null (!null implicit, only if defined in the above 
way. Essentially an alias is created for us automatically)


Type(T) : Type!nullinherits only if T is not null(or a type 
that inherits from itself,  which would then be valid).


Type!Dog inherits from Type/Type!null.

Type!T inherits from Type/Type!null as long as T != null.

Members in base(null) are not re-included in derived(e.g., int 
x; isn't include in Type!Dog because it's already there from 
base).


Something like this:

class Type(T: typeof(null)) { //< L1 (specialization)
int x;
}

class Dog {}

class Type(T) : Type!(typeof(null)) { //< L2 (`typeof(null)`)
static if(is(T: Dog)) //< L3 (`is(MyType: IntendedType)` or 
`is(MyType == ExactType)`)

int y;
}

What you're looking for is "specialization", on line "L1". Also 
some corrections on lines "L2" and "L3"


Re: How about a special null template parameter?

2016-08-19 Thread Engine Machine via Digitalmars-d

On Friday, 19 August 2016 at 21:07:42 UTC, Timon Gehr wrote:

On 19.08.2016 20:25, Engine Machine wrote:

So we can create types relationships easier:

class Type(T) : Type!null
{
   int x;
   static if (T is Dog)
   int y;



alias Seq(T...)=T;

template TypeParent(T...) if(T.length==1){
static if(is(typeof(T[0])==typeof(null))) alias TypeParent 
= Seq!();

else alias TypeParent = Seq!(Type!null);
}

class Type(T...): TypeParent!T if(T.length==1){
   int x;
   static if (T is Dog)
   int y;
}


This is a bit verbose and not quite right (T is Dog should be 
something like T[0], or whatever).


It does essentially work. My only complaint is that it would be 
nice to be able to export an alias to Type!() = Type; in the 
namespace of the type being created. Doubt that D can do that!? 
If it can, then it should be an adequate solution.


That is

It would be nice to have something like

alias Type = Type!();
class Type(T...): TypeParent!T if(T.length==1){
int x;
static if (T is Dog)
int y;
}

Again, I don't think D will allow this.


alias Seq(T...)=T;

template TypeParent(T...) {
static if(is(typeof(T[0])==typeof(null))) alias TypeParent = 
Seq!();

else alias TypeParent = Seq!(Type!null);
}

class Type(T...) : TypeParent!T
{
   int x;
   static if(T.length == 1)
   {
static if (T[0] is Dog)
int y;
   }
}

(note I removed the length checks, so we can create the base type 
and such)


I guess a such a method is nice to create compound types though:

Type!(Animal, Dog, Chihuahua)

and have a inheritance chain.

e.g.,


class Type(T...) : TypeParent!T
{
   int x;
   static if(T.length >= 1)
   {
static if (T[0] is "Animal")
{
int z;
static if (T[1] is "Dog")
int y;
}
   }
}


void main()
{
Type!("Animal", "Dog") t;
}

I don't know if all this obeys inheritance though but it looks 
like it should.


Thanks!


Re: How about a special null template parameter?

2016-08-19 Thread Engine Machine via Digitalmars-d
On Friday, 19 August 2016 at 19:19:35 UTC, Lodovico Giaretta 
wrote:

On Friday, 19 August 2016 at 18:25:06 UTC, Engine Machine wrote:

So we can create types relationships easier:

class Type(T) : Type!null
{
   int x;
   static if (T is Dog)
   int y;
}

Type == Type!null (!null implicit, only if defined in the 
above way. Essentially an alias is created for us 
automatically)


Type(T) : Type!nullinherits only if T is not null(or a type 
that inherits from itself,  which would then be valid).


Type!Dog inherits from Type/Type!null.

Type!T inherits from Type/Type!null as long as T != null.

Members in base(null) are not re-included in derived(e.g., int 
x; isn't include in Type!Dog because it's already there from 
base).


This simple syntactic sugar allows us to create multiple 
classes to create simple inheritance hierarchy.


It replaces the current method of having to define a 
non-templated class and a templated class.


e.g.,

class Type
{
   int x;
}

class Type(T) : Type
{
   static if (T is Dog)
  int y;
}



vs



class Type(T) : Type!null
{
   int x;
   static if (T is Dog)
   int y;
}


1) `null` has a very precise meaning: it is the only valid 
value of an unnamed type only known as `typeof(null)`, which 
implicitly converts to any class/pointer/dynamic 
array/associative array type. Thus this thing should have a 
different name.


null as many interpretations. It is ok to expand the meaning. It 
is done all the time. If it confuses you are creates a semantic 
difficulty, I don't mind what it is called. It could be called 
Boomfurkasufasdf.


In this case, defining it to be null fits in semantically though. 
If it creates some compiler issue then, again, anything else 
could be used. I'd prefer Null or NULL or Aleph or something 
short and meaningless.





2) What about this case:
```
class Type(T): Type
{
static if (T is Dog)
int y;
else
float z;
}
```
What should be inside the base?


z.


3) I guess that you may find this useful to write functions 
that accept any type this way:

```
void myFunction(Type val)
{
// only use fields in common between all Type instantiations
}
```
But you can already do that this way, which is way more 
flexible:

```
void myFunction(T)(Type!T val)
{
// use fields in common between all instantiation,
// but also fields specific to a certain instantiation,
// using static if
}
```


Well, that is not really what I'm after. I am after simplifying 
class design.


4) I think that the value of this addition is little wrt. the 
amount of work the compiler should do to implement it (which at 
first sight would be a lot). But this is of course just my 
opinion.


It is just syntactic sugar and requires no complex compiler 
modifications. The benefit is reduced visual complexity and that 
is always a bonus. That is the point we don't write in 0's and 
1's... everything else is just syntactic sugar. In this case, it 
is a very simple rewrite rule. A few lines of code would be all 
that is required.






Re: How about a special null template parameter?

2016-08-19 Thread Engine Machine via Digitalmars-d

On Friday, 19 August 2016 at 19:13:10 UTC, Jack Applegame wrote:

On Friday, 19 August 2016 at 18:25:06 UTC, Engine Machine wrote:
It replaces the current method of having to define a 
non-templated class and a templated class.


e.g.,

class Type
{
   int x;
}

class Type(T) : Type
{
   static if (T is Dog)
  int y;
}
What are you talking about? This code doesn't compile. Because 
you can't define a class and a template with the same name.


It doesn't matter. That is just a defect of D/language.

If it confuses you, call it Type_Special_X, or, if that confuses 
you, call it something else. Don't get caught up in the words old 
padawan.





Re: How about a special null template parameter?

2016-08-19 Thread Timon Gehr via Digitalmars-d

On 19.08.2016 20:25, Engine Machine wrote:

So we can create types relationships easier:

class Type(T) : Type!null
{
   int x;
   static if (T is Dog)
   int y;



alias Seq(T...)=T;

template TypeParent(T...) if(T.length==1){
static if(is(typeof(T[0])==typeof(null))) alias TypeParent = Seq!();
else alias TypeParent = Seq!(Type!null);
}

class Type(T...): TypeParent!T if(T.length==1){
   int x;
   static if (T is Dog)
   int y;
}



Re: How about a special null template parameter?

2016-08-19 Thread Lodovico Giaretta via Digitalmars-d

On Friday, 19 August 2016 at 18:25:06 UTC, Engine Machine wrote:

So we can create types relationships easier:

class Type(T) : Type!null
{
   int x;
   static if (T is Dog)
   int y;
}

Type == Type!null (!null implicit, only if defined in the above 
way. Essentially an alias is created for us automatically)


Type(T) : Type!nullinherits only if T is not null(or a type 
that inherits from itself,  which would then be valid).


Type!Dog inherits from Type/Type!null.

Type!T inherits from Type/Type!null as long as T != null.

Members in base(null) are not re-included in derived(e.g., int 
x; isn't include in Type!Dog because it's already there from 
base).


This simple syntactic sugar allows us to create multiple 
classes to create simple inheritance hierarchy.


It replaces the current method of having to define a 
non-templated class and a templated class.


e.g.,

class Type
{
   int x;
}

class Type(T) : Type
{
   static if (T is Dog)
  int y;
}



vs



class Type(T) : Type!null
{
   int x;
   static if (T is Dog)
   int y;
}


1) `null` has a very precise meaning: it is the only valid value 
of an unnamed type only known as `typeof(null)`, which implicitly 
converts to any class/pointer/dynamic array/associative array 
type. Thus this thing should have a different name.


2) What about this case:
```
class Type(T): Type
{
static if (T is Dog)
int y;
else
float z;
}
```
What should be inside the base?

3) I guess that you may find this useful to write functions that 
accept any type this way:

```
void myFunction(Type val)
{
// only use fields in common between all Type instantiations
}
```
But you can already do that this way, which is way more flexible:
```
void myFunction(T)(Type!T val)
{
// use fields in common between all instantiation,
// but also fields specific to a certain instantiation,
// using static if
}
```

4) I think that the value of this addition is little wrt. the 
amount of work the compiler should do to implement it (which at 
first sight would be a lot). But this is of course just my 
opinion.


Re: How about a special null template parameter?

2016-08-19 Thread Jack Applegame via Digitalmars-d

On Friday, 19 August 2016 at 18:25:06 UTC, Engine Machine wrote:
It replaces the current method of having to define a 
non-templated class and a templated class.


e.g.,

class Type
{
   int x;
}

class Type(T) : Type
{
   static if (T is Dog)
  int y;
}
What are you talking about? This code doesn't compile. Because 
you can't define a class and a template with the same name.