www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - How to do Generic Programming in D?

reply Nick <nick example.com> writes:
Coming from Andrei's work in C++ "Modern C++ Programming" I wonder how 
to implement many of those patterns in D?

In C++ I would work with type lists and use lots of multiple inheritance 
and templates to get the magic I need.

D lacks MI, classes and delegates seem heavy (allocated on heap, with 
one extra pointer and new for each delegate) and has instead template 
mixins which do not create types and string mixing which create... anything.

So I am a bit lost.

I guess I am looking for some code&examples to read to "get" GP in D. A 
bit like "Modern C++ Programming".

Of course, the basic question being: is D2 sufficient to support 
everything that is possible in C++?

Thanks!
Feb 22 2011
next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Nick" <nick example.com> wrote in message 
news:ik11ot$2fms$1 digitalmars.com...
 Coming from Andrei's work in C++ "Modern C++ Programming" I wonder how to 
 implement many of those patterns in D?

 In C++ I would work with type lists and use lots of multiple inheritance 
 and templates to get the magic I need.

I abandoned C++ about 10 years ago so I don't know anything about the patterns you're talking about, but:
 D lacks MI,

Replaced by either mixins or interfaces, depending on what you're trying to do.
 classes and delegates seem heavy (allocated on heap, with one extra 
 pointer and new for each delegate)

IIRC, non-heap-based value-semantics classes are kind of rare in C++. If you want a value-semantics "class" in D, you use a struct. You give up the ability to subclass, but I've heard there are major problems combining inheritence with value-semantics even in C++ anyway.
 I guess I am looking for some code&examples to read to "get" GP in D. A 
 bit like "Modern C++ Programming".

If by "GP" you mean generic programming, then the primary mechanisms for that in D are CTFE (compile-time function execution), templates and string/template mixins.
Feb 22 2011
parent "Nick Sabalausky" <a a.a> writes:
"Nick Sabalausky" <a a.a> wrote in message 
news:ik14sh$2lfi$1 digitalmars.com...
 "Nick" <nick example.com> wrote in message 
 news:ik11ot$2fms$1 digitalmars.com...
 Coming from Andrei's work in C++ "Modern C++ Programming" I wonder how to 
 implement many of those patterns in D?

 In C++ I would work with type lists and use lots of multiple inheritance 
 and templates to get the magic I need.

I abandoned C++ about 10 years ago so I don't know anything about the patterns you're talking about, but:
 D lacks MI,

Replaced by either mixins or interfaces, depending on what you're trying to do.

Oh, and also "alias this" which, as explained in Andrei's book "The D Programming Language" can be a very useful alternative to MI, particularly when combined with nested classes. "alias this" is also good for subtyping structs, even though structs still aren't polymorphic. Like Jason said, if you have specific examples of idioms, we can translate to D for you.
Feb 22 2011
prev sibling next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Nick:

 Coming from Andrei's work in C++ "Modern C++ Programming" I wonder how 
 to implement many of those patterns in D?

Those code patterns come from many years of C++ practice from lot of C++ programmers. D2 is not so old and so used, so probably some of the idioms of D2 are yet to be invented :-)
 In C++ I would work with type lists and use lots of multiple inheritance 
 and templates to get the magic I need.

In D there are templates and TypeTuples, etc.
 D lacks MI, classes and delegates seem heavy (allocated on heap, with 
 one extra pointer and new for each delegate) and has instead template 
 mixins which do not create types and string mixing which create... anything.

D also has not-closure delegates (using scope, sometimes it works), function pointers, etc.
 So I am a bit lost.

D shares some things with C++, but you need to learn to use new idioms. When you go from language X to language Y there are often ways to implement the same algorithm Y too, but you need Y-specific idioms to do it. I suggest you to read the online D documentation and then Phobos code.
 Of course, the basic question being: is D2 sufficient to support 
 everything that is possible in C++?

Who knows. The answer is probably positive, but you need some creativity. Bye, bearophile
Feb 22 2011
prev sibling next sibling parent Jason House <jason.james.house gmail.com> writes:
Nick Wrote:

 Coming from Andrei's work in C++ "Modern C++ Programming" I wonder how 
 to implement many of those patterns in D?
 
 In C++ I would work with type lists and use lots of multiple inheritance 
 and templates to get the magic I need.

I don't have the book, but I'm sure that if you posted an example task, someone here (or on d.learn) would translate it using their favorite D style.
 D lacks MI, classes and delegates seem heavy (allocated on heap, with 
 one extra pointer and new for each delegate) and has instead template 
 mixins which do not create types and string mixing which create... anything.

Nick addressed some of these already. I thought delegates were passed like a struct on the stack. The extra pointer in a delegate seems handy to me. It's much cleaner than what C++ does. There's also C-like function pointers. You also left out "static if", compile-time function execution, and is expressions. They replace a lot of the required magic from C++. A lot of people swear by string mixins, but I use them sparingly. There's also conditional templates which I've never used, but look useful.
 
 So I am a bit lost.
 
 I guess I am looking for some code&examples to read to "get" GP in D. A 
 bit like "Modern C++ Programming".
 
 Of course, the basic question being: is D2 sufficient to support 
 everything that is possible in C++?
 
 Thanks!

Feb 22 2011
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/22/11 1:04 PM, Nick wrote:
 Coming from Andrei's work in C++ "Modern C++ Programming" I wonder how
 to implement many of those patterns in D?

 In C++ I would work with type lists and use lots of multiple inheritance
 and templates to get the magic I need.

 D lacks MI, classes and delegates seem heavy (allocated on heap, with
 one extra pointer and new for each delegate) and has instead template
 mixins which do not create types and string mixing which create...
 anything.

 So I am a bit lost.

 I guess I am looking for some code&examples to read to "get" GP in D. A
 bit like "Modern C++ Programming".

 Of course, the basic question being: is D2 sufficient to support
 everything that is possible in C++?

 Thanks!

Welcome to the group. Using D for the kind of generic designs featured in MC++D may be a bit disconcerting because a lot of the C++ implementation is forced to use unintuitive mechanisms to get things done. The expectation is that the same mechanisms need to be used for the D implementation, too, which shouldn't be the case. In fact accomplishing any of MC++D's tasks is considerably easier in D. For example, indeed in C++ a policy-based design would need to use multiple inheritance. But this is not motivated by a need for multiple subtyping - MI is just the best proxy C++ has for injecting parameterized implementation. In D for that goal you'd use mixin templates, or for ultimate flexibility string mixins. If you do need multiple subtyping, you'd use classes in conjunction with e.g. parameterized interfaces and/or "alias this". Typelists are an elaborate C++ construct that is essentially built in into D. For the Command pattern, delegates would be a great start. Added value for e.g. currying and binding is trivial to implement, to the extent that we decided to deprecate a dedicated module (std.bind). There would be more to say. One way or another, policy-based design is difficult and often unintuitive. Therefore, it requires mastery of both the design topic at hand and of the implementation language. I think trying to get a solid PBD component off the ground as a D beginner would be pushing it. Nevertheless, it may be worth a try. I suggest starting with a simple, well-defined component such as Object Factory. Andrei
Feb 22 2011
parent reply Nick <nick example.com> writes:
On 2/23/2011 12:35 AM, Andrei Alexandrescu wrote:
 On 2/22/11 1:04 PM, Nick wrote:
 Coming from Andrei's work in C++ "Modern C++ Programming" I wonder how
 to implement many of those patterns in D?

 In C++ I would work with type lists and use lots of multiple inheritance
 and templates to get the magic I need.

 D lacks MI, classes and delegates seem heavy (allocated on heap, with
 one extra pointer and new for each delegate) and has instead template
 mixins which do not create types and string mixing which create...
 anything.

 So I am a bit lost.

 I guess I am looking for some code&examples to read to "get" GP in D. A
 bit like "Modern C++ Programming".

 Of course, the basic question being: is D2 sufficient to support
 everything that is possible in C++?

 Thanks!

Welcome to the group. Using D for the kind of generic designs featured in MC++D may be a bit disconcerting because a lot of the C++ implementation is forced to use unintuitive mechanisms to get things done. The expectation is that the same mechanisms need to be used for the D implementation, too, which shouldn't be the case. In fact accomplishing any of MC++D's tasks is considerably easier in D. For example, indeed in C++ a policy-based design would need to use multiple inheritance. But this is not motivated by a need for multiple subtyping - MI is just the best proxy C++ has for injecting parameterized implementation. In D for that goal you'd use mixin templates, or for ultimate flexibility string mixins. If you do need multiple subtyping, you'd use classes in conjunction with e.g. parameterized interfaces and/or "alias this". Typelists are an elaborate C++ construct that is essentially built in into D. For the Command pattern, delegates would be a great start. Added value for e.g. currying and binding is trivial to implement, to the extent that we decided to deprecate a dedicated module (std.bind). There would be more to say. One way or another, policy-based design is difficult and often unintuitive. Therefore, it requires mastery of both the design topic at hand and of the implementation language. I think trying to get a solid PBD component off the ground as a D beginner would be pushing it. Nevertheless, it may be worth a try. I suggest starting with a simple, well-defined component such as Object Factory. Andrei

Thanks for all your replies! I was not sure about mixins: the template ones had a little warning in the book as being mostly experimental, and the string mixins, while powerful, seemed to me something closer to c++ macros than to the template/class/policies I knew. But I will look again. I will start slowly and defer to this list if I get stuck. Thanks!
Feb 23 2011
parent Simon <s.d.hammett gmail.com> writes:
On 23/02/2011 17:22, Nick wrote:
 On 2/23/2011 12:35 AM, Andrei Alexandrescu wrote:
 Andrei

Thanks for all your replies! I was not sure about mixins: the template ones had a little warning in the book as being mostly experimental, and the string mixins, while powerful, seemed to me something closer to c++ macros than to the template/class/policies I knew. But I will look again. I will start slowly and defer to this list if I get stuck. Thanks!

D is sufficiently close to C++ that I was able to port (most of) the classic version of boost::spirit to D in a month of my spare time. Spirit makes rather enthusiastic use of template meta programming; though not half as much as the new version. Most of that time was spent groking spirit rather than actually doing the D implementation as well. -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk
Feb 23 2011
prev sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
Nick wrote:
 Of course, the basic question being: is D2 sufficient to support
 everything that is possible in C++?

So far, everything I've tried has not only been possible, but quite a bit easier. Last weekend, I had to go back to C++ to do some quick work. I wanted to port a boxer function over. In D, I used a variadic template, foreach, and static if to it off. The code was about 100 lines long and either worked for all types or failed meaningfully. C++ couldn't take that approach. I figured I could get closer if I used some C++0x features, and since this project only had to work in environments I control, I enabled them and went to town. C++0x felt like a crippled, inelegant D. Yes, it has variadic templates, but without foreach, I had to use recursion to go over them. Without static if and template constraints, it was a mess of overloaded functions and what felt like horrible abuses of SFINAE. A simple looped assignment, 4 lines in D, became about 60 lines of bizarre overloads and recursion, and still didn't handle all the types quite as elegantly as D. When it was all said and done, the 100 lines of D became about 250 lines of C++0x. (There's other features that are pretty equal so it wasn't all so lopsided). Then, the real ugliness came in. In D, you can do compile time reflection. Want to automatically implement an interface with the boxer function? Another simple foreach loop with static ifs to round it off. I couldn't figure it out in C++. It was probably possible, but it was too hard for my simpleton brain to handle. I ended up writing a helper code generator for it. (btw, on code generators, if you write one in D, you can probably call it at compile time and generate the code all at once... no need for extra steps in your build process! See string mixins and CTFE for how. Short answer: write the code generator as a function returning a string with the code. Then do mixin(myCodeGenFunction()); It'll probably work!) That's the big difference between C++ and D. C++ makes it possible. D makes it accessible.
Feb 22 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Adam D. Ruppe:

 C++0x felt like a crippled, inelegant D. Yes, it has variadic
 templates, but without foreach, I had to use recursion to go
 over them. Without static if and template constraints, it was
 a mess of overloaded functions and what felt like horrible
 abuses of SFINAE.

Is this enough to make some C++ shops switch to D2? Firms that have megabytes of complex C++ legacy code are not going to translate it to D2 just because D2 has something nicer. And there are significant problems in integrating D2 code in C++ projects. The switch from C to C++ was much more smooth. And lot of people have already stopped using static compilers like C++ ones and have switched to the niceties of a virtual machine, dynamic compilation, etc. Bye, bearophile
Feb 22 2011
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
bearophile wrote:
 Is this enough to make some C++ shops switch to D2?

If they are doing new code, it should be! For existing code, that depends on their specific situation. The reason I was writing C++ recently though was Qt - I wanted to use existing code. (QtD is so, so close, but has some showstopper bugs on Windows and doubled the size of the distribution... so I instead wrote the GUI in C++ and the rest of the app in D. Then I got the best of both worlds.)
 Firms that have megabytes of complex C++ legacy code are not
 going to translate it to D2 just because D2 has something nicer.

Most likely, they aren't going to translate it *at all*. There's rarely a big benefit in translating code. But, when writing fresh code, those nicer things add up to a big difference.
 And there are significant problems in integrating D2 code in C++
 projects. The switch from C to C++ was much more smooth.

I don't know, I've never tried that. But integrating C++ into D2 apps isn't too bad.
 And lot of people have already stopped using static compilers
 like C++ ones and have switched to the niceties of a virtual
 machine, dynamic compilation, etc.

Their loss.
Feb 22 2011
parent reply "Paulo Pinto" <pjmlp progtools.org> writes:
How come is our loss?

I keep an eye on D and Go, because personally, I would like to see a 
language replace C and C++
as THE systems programming language.

But I hardly use any of them beside some toy examples, because on my part of 
the world,
be it with C++ or VM languages I am spoiled for choice in what concerns 
language stability and productivity.

When I see someone advocating a technology the will make everything better, 
I always remind
myself of "Worse is Better", principle.

It does not matter how good something is, in regards with what is actually 
being used, if the pain
to switch is too big for the beneficts that someone might gain, people don't 
switch. It is the human
nature.

--
Paulo

"Adam D. Ruppe" <destructionator gmail.com> wrote in message 
news:ik1n7d$k89$1 digitalmars.com...
 bearophile wrote:
 Is this enough to make some C++ shops switch to D2?

If they are doing new code, it should be! For existing code, that depends on their specific situation. The reason I was writing C++ recently though was Qt - I wanted to use existing code. (QtD is so, so close, but has some showstopper bugs on Windows and doubled the size of the distribution... so I instead wrote the GUI in C++ and the rest of the app in D. Then I got the best of both worlds.)
 Firms that have megabytes of complex C++ legacy code are not
 going to translate it to D2 just because D2 has something nicer.

Most likely, they aren't going to translate it *at all*. There's rarely a big benefit in translating code. But, when writing fresh code, those nicer things add up to a big difference.
 And there are significant problems in integrating D2 code in C++
 projects. The switch from C to C++ was much more smooth.

I don't know, I've never tried that. But integrating C++ into D2 apps isn't too bad.
 And lot of people have already stopped using static compilers
 like C++ ones and have switched to the niceties of a virtual
 machine, dynamic compilation, etc.

Their loss.

Feb 23 2011
parent Adam Ruppe <destructionator gmail.com> writes:
Paulo Pinto wrote:
 How come is our loss?

VMs come with a cost for what's really very little gain. You don't need a fancy VM to have a nice language.
 It does not matter how good something is, in regards with what is
 actually being used, if the pain to switch is too big for the
 beneficts that someone might gain, people don't switch.

This is why I don't use VMs (when I can avoid it)!
Feb 23 2011