June 21, 2008 Re: Template constraints in D | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bearophile | bearophile wrote:
> They look nice (but I may use a bigger list of examples to understand
> how they can be used). What can they do that can't be done with the
> things already present?
>
> bool isprime(int n) { ... } template Foo(int N) { static assert
> (isprime(N), "error"); ... }
>
>
> template Foo(int N) { static if (N & 1) { // A code } else { // B
> code } Foo!(3) // instantiates Foo with A code Foo!(64) //
> instantiates Foo with B code
Very good question. The answer is that the user can add overloads that handle more cases without having to edit the original (which may be in a module that is not editable for various reasons).
| |||
June 21, 2008 Re: Template constraints in D | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Ary Borenszweig | Ary Borenszweig wrote: > For me, this is the big difference between them: > > Semantic analysis of template bodies: > - D: Lazy (done at instantiation time) > - C++0x: Eager (done at definition time) > > I want to get errors in the template itself, not just know that I've done something wrong in my template when some user discovers a bug in it. I discussed this with Douglas Gregor, the primary inventor of concepts. It boiled down to, how likely is it that one would ship a template that had never been instantiated, and is that a big enough feature that it needs language support? > This will also enable IDE support for templates. I don't see how that is required for IDE support. | |||
June 21, 2008 Re: Template constraints in D | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | Walter Bright wrote: > Bill Baxter wrote: >> A more natural way to declare required functions would be nice. >> >> First of all, about the isAddable example, can't you just use T.init instead of writing an anonymous delegate? Like >> __traits(compiles, T.init + T.init) > > I think you're right. > >> Anyway, for a less trivial example I think that becomes pretty cumbersome. E.g.: >> >> concept Stack<typename X> { >> typename value_type; >> void push(X&, const value_type&); >> void pop(X&); >> value_type top(const X&); >> bool empty(const X&); >> }; >> >> is going to translate to something like this?: >> >> template Stack(T) >> { >> const Stack = >> is(T.value_type) && >> __traits(compiles, (T t, T.value_type v) { push(t, v); }) && >> __traits(compiles, (T t) { pop(t); }) && >> __traits(compiles, (T t) { top(t); }) && >> is(typeof(top(T.init))==T.value_type) && >> __traits(compiles, (T t) { empty(t) }) && >> is(typeof(empty(T.init))==bool); >> } >> >> I hope you can work out a way to give this a more natural syntax, like Concepts will have in C++0x. > > You're the first I've heard say that Concepts have a natural syntax! Well, I didn't go very far into that spec document you link to, but I think the Stack example above (which I took from there) is really straightforward. It looks just like a kind of interface declaration. Since concepts are trying to express compile-time interfaces, that makes plenty of sense. > But let me try: > > template Stack(T) > { > const Stack = > __traits(compiles, > (T t) > { T.value_type v = top(t); > push(t, v); > pop(t); > if (empty(t)){} > }); > } > > The idea is that the desired operations are expressed as operations, rather than as function signatures. I do like the idea -- show the actual code you want to work, not something one-step removed like "has an opAdd member". Still, anything containing __traits looks like an afterthought. Also, I'm not sure how it's going to work in C++, but isn't the compiler going to have a hard time reporting errors in that kind of thing? Failure to instantiate could be because of a very minor typo in the big list of constraints. I'm not sure how C++ will deal with that, but I think it's another place where concept maps help. They introduce a little redundancy. They give you a place to say "I think type X satisfies concept Y, and here's how". That gives the compiler a place to say, "No you're wrong, type X does not satisfy concept Y because Foo isn't actually a method of X". It seems like it should be possible to generate very readable error messages from that. >> An unrelated comment is that I don't think it is relevant or respectful to compare the lengths of the specs. The spec for Concepts that you link to includes many many more in depth examples than the D spec does. It's an apples vs oranges comparison. So 5 pages vs 49 pages really doesn't have much meaning at all. > > I wished to make the point that D constraints build on what one already knows - how to write a D expression. Concepts, on the other hand, have a major new syntax and semantic thing that must be learned. Perhaps I expressed the point badly, do you have a suggestion? I think the number of new keywords expresses that well enough. You could also add something like "new syntactic constructs: 1 vs [however many concepts add]". I think you can pretty much count up the gray boxes in the Concepts spec to get that number. Or maybe call it "new productions added to grammar". --bb | |||
June 21, 2008 Re: Template constraints in D | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | Walter Bright Wrote:
> bearophile wrote:
> > They look nice (but I may use a bigger list of examples to understand how they can be used). What can they do that can't be done with the things already present?
> >
> > bool isprime(int n) { ... } template Foo(int N) { static assert
> > (isprime(N), "error"); ... }
> >
> >
> > template Foo(int N) { static if (N & 1) { // A code } else { // B
> > code } Foo!(3) // instantiates Foo with A code Foo!(64) //
> > instantiates Foo with B code
>
> Very good question. The answer is that the user can add overloads that handle more cases without having to edit the original (which may be in a module that is not editable for various reasons).
Good example is a hashtable. If the bucket size is prime then use a strategy. If is a power of two use another strategy. Otherwise use third strategy. Thanks, Dee Girl
| |||
June 21, 2008 Re: Template constraints in D | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | Walter Bright Wrote: > You're the first I've heard say that Concepts have a natural syntax! But let me try: > > template Stack(T) > { > const Stack = > __traits(compiles, > (T t) > { T.value_type v = top(t); > push(t, v); > pop(t); > if (empty(t)){} > }); > } > > The idea is that the desired operations are expressed as operations, rather than as function signatures. I think is much easier another way. void stackConcept(T)() { T t; T.value_type v = top(t); push(t, v); pop(t); if (empty(t)){} } You simply call is(typeof(stackConcept!(T))) after. It is Very easy. > > An unrelated comment is that I don't think it is relevant or respectful > > to compare the lengths of the specs. The spec for Concepts that you > > link to includes many many more in depth examples than the D spec does. > > It's an apples vs oranges comparison. So 5 pages vs 49 pages really > > doesn't have much meaning at all. > > I wished to make the point that D constraints build on what one already knows - how to write a D expression. Concepts, on the other hand, have a major new syntax and semantic thing that must be learned. Perhaps I expressed the point badly, do you have a suggestion? I hope this is not offensive. I said one that you focus on comparing D with C++ to much. And again you do the same with concepts. Comparison by any body else that you is ok. But if you do comparison is terrible. Makes you look second in run trying to reach first. You are not loser and do not want to look like loser. I study kyokushin karate 9 year. I was not good ^_^ but it was good for me. Sensei said many times best karate ka not compete with others. He compete with himself. Best fighter wants to do his best not only better than others. I understood him after years. I hope I express myself ok. One thing is also you implemented functionality in C++ concepts. Implementation is clever. But you do not bring original thing. You do what the C++ documentation does. Nothing else. It is not creative and not original. D is not C++ monkey. Stop looking at C++, do what you know is good; and you will be happy. Sorry, Dee Girl | |||
June 22, 2008 Re: Template constraints in D | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bearophile | == Quote from bearophile (bearophileHUGS@lycos.com)'s article > Walter Bright: > > http://www.digitalmars.com/d/2.0/concepts.html > They look nice (but I may use a bigger list of examples to understand how they can be used). What can they do that can't be done with the things already present? Nothing. But it's a very convenient syntactic sugar on top of existing techniques, such as: http://www.digitalmars.com/d/archives/digitalmars/D/Stroustrup_s_talk_on_C_0x_57104.html#N5737 9 Walter had even asked me to write an article about this, but I never followed through :p I will say that the __traits(compiles, blah) trick is totally awesome. I was trying to do this in D 1.0 the other day and couldn't find a way to make it work. Figures it would require D 2.0. *sigh* Sean | |||
June 22, 2008 Re: Template constraints in D | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Sean Kelly | Sean Kelly wrote: > == Quote from bearophile (bearophileHUGS@lycos.com)'s article >> Walter Bright: >>> http://www.digitalmars.com/d/2.0/concepts.html >> They look nice (but I may use a bigger list of examples to understand how they can be used). What > can they do that can't be done with the things already present? > > Nothing. But it's a very convenient syntactic sugar on top of existing > techniques, such as: > > http://www.digitalmars.com/d/archives/digitalmars/D/Stroustrup_s_talk_on_C_0x_57104.html#N5737 > 9 > > Walter had even asked me to write an article about this, but I never > followed through :p > > I will say that the __traits(compiles, blah) trick is totally awesome. I > was trying to do this in D 1.0 the other day and couldn't find a way to > make it work. Figures it would require D 2.0. *sigh* DeeGirl's trick works in D 1.x doesn't it? I.e. a template function + is(typeof(thatTemplateFunction!(T))) --bb | |||
June 22, 2008 Re: Template constraints in D | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Dee Girl | Dee Girl wrote:
> Walter Bright Wrote:
>
>> bearophile wrote:
>>> They look nice (but I may use a bigger list of examples to understand
>>> how they can be used). What can they do that can't be done with the
>>> things already present?
>>>
>>> bool isprime(int n) { ... } template Foo(int N) { static assert
>>> (isprime(N), "error"); ... }
>>>
>>>
>>> template Foo(int N) { static if (N & 1) { // A code } else { // B
>>> code } Foo!(3) // instantiates Foo with A code Foo!(64) //
>>> instantiates Foo with B code
>> Very good question. The answer is that the user can add overloads that handle more cases without having to edit the original (which may be in a module that is not editable for various reasons).
>
> Good example is a hashtable. If the bucket size is prime then use a strategy. If is a power of two use another strategy. Otherwise use third strategy. Thanks, Dee Girl
I agree, that's a good example.
-Joel
| |||
June 22, 2008 Re: Template constraints in D | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | Walter Bright wrote: > > (Also comparing them with C++0x concepts.) > > http://www.digitalmars.com/d/2.0/cpp0x.html#concepts > > http://www.digitalmars.com/d/2.0/concepts.html > > Essentially, I think we cover the necessary ground with an order of magnitude simpler system. As I understand it, one thing C++0x concepts will be able to do is resolve collisions/overloading in a reasonable way. Can someone can inherit from say isAddable and then write a specialized template for that? Furthermore is there a way to specialize something like: template Foo(T, int N) if (isAddable!(T) && isprime(N)) Once someone has already written that in another lib and you want to add something like: template Foo(T, int N) if (isAddable!(T) && isprime(N) && isLessThen(N, 100)) Can the compiler figure out which to use? Maybe it could in this case, but in more complex example what would it choose? One way that would be possible is to write a new template with a different name that calls Foo. However that's not ideal because then you can't optimize (for instance) places where Foo is already in use. -Joel | |||
June 22, 2008 Re: Template constraints in D | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | Walter Bright wrote: > Lutger wrote: >> Very much so, brilliant! But what about concept maps, the suggestion is to use proxy objects but won't that be very cumbersome? Aren't concept maps important enough? > > I think I understand concept maps, but I don't understand what the compelling use case for their existence is. In C++ or possibly in D? In this talk - probably posted before - Douglas Gregor also talks about the uses for concept maps, about ten minutes from 36.00 or so: http://www.youtube.com/watch?v=Ot4WdHAGSGo From that talk, as far as I could understand, I think these were the most important aspects: - concept maps are needed to implement the C++ equivalent of D's opApply operator. - they replace the existing ways to define new iterators - map the interface of built-in types to concepts - concept maps make it possible to define partial ordering rules between existing types that you cannot alter. This is not relevant in D right? In general, because concept maps can be used with existing types, they allow for backwards compatibility and increased functionality of existing code. Template constraints make it possible (or much easier) to extend existing templates via overloading, concept maps complete this extensibility in the case both the type and the template exist and are compatible by concept but not syntax, D. Gregor calls this 'syntax remapping'. Whether this is compelling *for D* I don't know. | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply