www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Template constraints

reply "bearophile" <bearophileHUGS lycos.com> writes:
Observe:

https://github.com/D-Programming-Language/phobos/pull/3054

Is this change the partial proof of another failure of a part of 
D language design? What's the point of template constraints? 
Aren't C++ Concepts better? Or to rephrase that in a less 
trollish way, can D be enhanced to add user-defined error 
messages to template constraints, and is such enhancement a good 
idea?

Bye,
bearophile
Mar 15 2015
parent reply "w0rp" <devw0rp gmail.com> writes:
On Sunday, 15 March 2015 at 08:29:01 UTC, bearophile wrote:
 Observe:

 https://github.com/D-Programming-Language/phobos/pull/3054

 Is this change the partial proof of another failure of a part 
 of D language design? What's the point of template constraints? 
 Aren't C++ Concepts better? Or to rephrase that in a less 
 trollish way, can D be enhanced to add user-defined error 
 messages to template constraints, and is such enhancement a 
 good idea?

 Bye,
 bearophile
It's funny you mentioned concepts, because I was just watching Bjarne's CppCon 2014 keynote again and I took away two things from it. 1. For the overwhelming majority of things Bjarne wants from C++ mentioned in that keynote, D has done all of them, and better... 2. ...except for concepts. I believe D does the template error message thing a *whole lot* better than C++. That's all because of template constraints, static if, and static assert, and I believe those are down to Andrei's influence. (Though others likely deserve credit for their design, implementation, and maintenance. As always you'll probably have to nod to Kenji who works like crazy.) I've been wondering what we can do to make specifying constraints for something like ranges a little easier to write, with obviously some underlying complexities which will be hard to implement. This doesn't address your concern about error messages for constraints really, but what I've thought of is roughly this. Say you write 'copy' currently. You'll do something like this. void copy(InputRange, OutputRange)(InputRange inputRange, OutputRange) if (isInputRange!InputRange && isOutputRange!OutputRange) { /* Some implementation of copying. */ } Maybe you'll use less verbose names and all kinds of things, but essentially that is what you're after. I've been wondering if it's possible to use compiler magic to make this possible. // These names conflict with our interfaces in std.range, whatever, imagine // some other name place of them if you like. template InputRange(T) { enum InputRange = isInputRange!T; } // The newer syntax makes the above easier... enum OutputRange(T) = isOutputRange!T; // Now this works with magic... void copy()(InputRange inputRange, OutputRange outputRange) { /* Some implementation of copying. */ } If you write this now, the compiler will print an error saying, "Hey, you just attempted to use this template which takes one argument as a type in this paramter list right here." My idea is to take that information and instead of returning an error, just go, "Oh, I'll just add another template parameter onto the end of your template parameter list here, replace the thing which really should be a type here with T from the parameter list, use deduction to insert the type for T and then use it, then use the template you had originally as a test on the type T yielding our boolean expression." I left the extra parens in there for 'copy' as I reckon they'll probably be a requirement anyway, and then you can't make accidental templates. You might have to read what I wrote four times to make sense of it, but that's my crazy idea others can destroy. I'm more of a wild idea guy than a formal specification guy.
Mar 15 2015
parent reply "matovitch" <camille.brugel laposte.net> writes:
On Sunday, 15 March 2015 at 10:40:17 UTC, w0rp wrote:
 On Sunday, 15 March 2015 at 08:29:01 UTC, bearophile wrote:
 Observe:

 https://github.com/D-Programming-Language/phobos/pull/3054

 Is this change the partial proof of another failure of a part 
 of D language design? What's the point of template 
 constraints? Aren't C++ Concepts better? Or to rephrase that 
 in a less trollish way, can D be enhanced to add user-defined 
 error messages to template constraints, and is such 
 enhancement a good idea?

 Bye,
 bearophile
It's funny you mentioned concepts, because I was just watching Bjarne's CppCon 2014 keynote again and I took away two things from it. 1. For the overwhelming majority of things Bjarne wants from C++ mentioned in that keynote, D has done all of them, and better... 2. ...except for concepts. I believe D does the template error message thing a *whole lot* better than C++. That's all because of template constraints, static if, and static assert, and I believe those are down to Andrei's influence. (Though others likely deserve credit for their design, implementation, and maintenance. As always you'll probably have to nod to Kenji who works like crazy.) I've been wondering what we can do to make specifying constraints for something like ranges a little easier to write, with obviously some underlying complexities which will be hard to implement. This doesn't address your concern about error messages for constraints really, but what I've thought of is roughly this. Say you write 'copy' currently. You'll do something like this. void copy(InputRange, OutputRange)(InputRange inputRange, OutputRange) if (isInputRange!InputRange && isOutputRange!OutputRange) { /* Some implementation of copying. */ } Maybe you'll use less verbose names and all kinds of things, but essentially that is what you're after. I've been wondering if it's possible to use compiler magic to make this possible. // These names conflict with our interfaces in std.range, whatever, imagine // some other name place of them if you like. template InputRange(T) { enum InputRange = isInputRange!T; } // The newer syntax makes the above easier... enum OutputRange(T) = isOutputRange!T; // Now this works with magic... void copy()(InputRange inputRange, OutputRange outputRange) { /* Some implementation of copying. */ } If you write this now, the compiler will print an error saying, "Hey, you just attempted to use this template which takes one argument as a type in this paramter list right here." My idea is to take that information and instead of returning an error, just go, "Oh, I'll just add another template parameter onto the end of your template parameter list here, replace the thing which really should be a type here with T from the parameter list, use deduction to insert the type for T and then use it, then use the template you had originally as a test on the type T yielding our boolean expression." I left the extra parens in there for 'copy' as I reckon they'll probably be a requirement anyway, and then you can't make accidental templates. You might have to read what I wrote four times to make sense of it, but that's my crazy idea others can destroy. I'm more of a wild idea guy than a formal specification guy.
I am not sure of what you want to do but that looks like "meta-type" like : void copy(InputRange IRage, OutputRange ORange) (IRange src, Orange dest) { /* Some implementation of copying. */ } Hashkell has something like that for a long times (early 90s I think) wich is call type classes. Essentially, it checks that the type implement a certain interface (operators included). You could do the same in c++ with boost (now maybe std)::is_base_of I think.
Mar 15 2015
parent "matovitch" <camille.brugel laposte.net> writes:
Sorry for the mistakes in the above message (and in this one). I 
didnt gave earlier my personnal opinion on the matter but 
essentially if I like the syntax of type classes very much, you 
can do much more with templates constraint and D meta programming 
abilities...But you still have to fix some kind of pragmatic 
limit in the compile time introspection I think...
Mar 15 2015