digitalmars.D - Templates everywhere
- Philippe Sigaud (6/6) Mar 14 2010 I was looking at some of my code today, I was surprised to see it was al...
- Nick Sabalausky (17/30) Mar 14 2010 "Do other have a similar evolution?"
- Philippe Sigaud (9/19) Mar 14 2010 I must have had bad experiences with pointers, because even now I cringe
- Walter Bright (35/38) Mar 14 2010 Years ago, although I had implemented templates for C++, I didn't "get"
- bearophile (12/14) Mar 14 2010 I agree that D syntax makes templates simpler (and the semantics too has...
- bearophile (5/6) Mar 14 2010 This is incredible. Thank you for this information :-)
- Philippe Sigaud (19/39) Mar 14 2010 That's interesting to know that you could implement templates, without
- Walter Bright (9/17) Mar 14 2010 I think of it like a race car builder. I can build the cars, but I can't...
- Bane (2/30) Mar 14 2010 They say you understand stuff only after you make it, not before.
- Walter Bright (3/20) Mar 14 2010 Ya know what's funny? I had to go and double check that the C++ syntax
- Bane (2/24) Mar 15 2010 D's example has look and feel of D, so it's intuitive. C++'s example may...
- Max Samukha (52/72) Mar 15 2010 Though I love D's templates:
- Walter Bright (2/4) Mar 15 2010 Thanks, I've incorporated it.
- Jason House (10/14) Mar 14 2010 I started with a basic comfort with templates and generalizing code, but...
- Walter Bright (7/28) Mar 14 2010 module foo;
- Eldar Insafutdinov (2/7) Mar 15 2010 Thanks for that, but what about the other issues, why does this function...
- Walter Bright (7/17) Mar 15 2010 Doing it that way is non-trivial, and I was in a hurry to get the system...
- Eldar Insafutdinov (34/56) Mar 15 2010 This code:
I was looking at some of my code today, I was surprised to see it was almost 100% templated: functions, mixin, structs, 'real' templates, what have you. Apart from main, what I write these days is full of (U,T...) if () {} and templates of templates of templates. That's quite an evolution, because when I discovered D 2 years ago coming from C++, I only used foreach and dynamic arrays. In C++, I never had any reason to create my own templates and couldn't wrap my head around anything template-y more complicated than 'containers of T'. Today I think in templates (well, at least I try to...). So: 1- thanks Walter for opening new vistas to me. Doing templated code in D is so fun and powerful that you transformed forever the way I look at problems. 2- Do other have a similar evolution? Philippe
Mar 14 2010
"Philippe Sigaud" <philippe.sigaud gmail.com> wrote in message news:hnitl9$1kpg$1 digitalmars.com...I was looking at some of my code today, I was surprised to see it was almost 100% templated: functions, mixin, structs, 'real' templates, what have you. Apart from main, what I write these days is full of (U,T...) if () {} and templates of templates of templates. That's quite an evolution, because when I discovered D 2 years ago coming from C++, I only used foreach and dynamic arrays. In C++, I never had any reason to create my own templates and couldn't wrap my head around anything template-y more complicated than 'containers of T'. Today I think in templates (well, at least I try to...). So: 1- thanks Walter for opening new vistas to me. Doing templated code in D is so fun and powerful that you transformed forever the way I look at problems. 2- Do other have a similar evolution?"Do other have a similar evolution?" As far as D specifically, the only evolution in me I can think of is this nice habit of being able to deal with code without getting absolutely fed up every three minutes (I had come from C++). It has also gotten me in the habit of certain good practices (like generic programming, for instance) which I [try to] bring with me as much as possible when I have to use a lesser langauge. I have had other things in the past though. When I first moved from BASIC to C (forever ago) I couldn't understand the usefulness of pointers (all the examples I saw in books seemed to do nothing more than create a redundant alias for a varaible that already existed in the same scope). Then I read some books about game development (on DOS), which involved a lot of storing data in buffers. That got me to understand how (at least in C) an array is just a pointer to a buffer but with prettier syntax, and then it all finally clicked.
Mar 14 2010
On Sun, Mar 14, 2010 at 19:37, Nick Sabalausky <a a.a> wrote:I have had other things in the past though. When I first moved from BASIC to C (forever ago) I couldn't understand the usefulness of pointers (all the examples I saw in books seemed to do nothing more than create a redundant alias for a varaible that already existed in the same scope). Then I read some books about game development (on DOS), which involved a lot of storing data in buffers. That got me to understand how (at least in C) an array is just a pointer to a buffer but with prettier syntax, and then it all finally clicked.I must have had bad experiences with pointers, because even now I cringe whenever I use one. I get the feeling I'm walking on ice, or something. That's strange because they were almost the first thing they taught me in CS courses a long time ago. You'd think I'd get used to them. Eh, when I use string mixins in D, I feel dirty, as if I was cheating somehow. Like, using cheat codes or something. I do not have this impression when doing macros in Lisp. Philippe
Mar 14 2010
Philippe Sigaud wrote:1- thanks Walter for opening new vistas to me. Doing templated code in D is so fun and powerful that you transformed forever the way I look at problems.Years ago, although I had implemented templates for C++, I didn't "get" them. Not at all. I didn't even plan to put templates in D, because they seemed overly complex, ugly, and had little value. It was pretty obvious, though, that the C++ community did get templates and did find them very useful. Something was wrong with my perception. I eventually realized that what was preventing me from understanding C++ templates was the syntax. Change the syntax, and what is happening suddenly becomes obvious. ======= C++ ========= template<class T> class Foo { T member; }; ======= D =========== class Foo(T) { T member; } ===================== Yes, it looks like a trivial change, and perhaps it is. But it makes a world of difference, because it now looks like something I do get - a parameter list to something. I had another epiphany from watching Scott Meyers give a presentation about an application for templated type lists in C++. Nearly the full hour was spent detailing a titanic struggle with the syntax. I suddenly realized that the whole presentation would have been over in 5 minutes if the syntax of type lists was simply that of an array of types. We already understand arrays of values, so why should an array of types be any different? It isn't the concept or application of templates that is hard. It's the C++ syntax for them that's hard. It's hard in C++ because when they were designed, little was known or understood about what templates were good for and how they should be used. Now that we do know, we can make a much more straightforward design.
Mar 14 2010
Walter Bright:Years ago, although I had implemented templates for C++, I didn't "get" them. Not at all.<It isn't the concept or application of templates that is hard. It's the C++ syntax for them that's hard. It's hard in C++ because when they were designed, little was known or understood about what templates were good for and how they should be used. Now that we do know, we can make a much more straightforward design.<I agree that D syntax makes templates simpler (and the semantics too has being cleaned up), and I like them in D. What's the purpose of templates in D? I think they have few main purposes: 1) Allow for type-safe compile-time genericity for collections and algorithms. 2) Perform some kind of usually simple "processing" on types, for example to determine what's the output type given two different input types. So types can be seen as compile-time variabiles for templates. Such processing is often related to the first purpose. 3) They can be used to perform compile-time computations on variables, for example to fill a data structure at compile-time. This is useful, but much less useful than the first two purposes of templates. Today in D this can often be done by CTFE that is getting better and better (thanks to Don too), so often today in D it's bad to use templates for this purposes. CTFE functions can be templated, so they can sometimes do what pure templates can do over types, with a much better syntax. templates, their purpose is mostly the first one in my list. Being less powerful they can (in theory) keep the language simpler to learn and use (in specify a collection to be covariant, contravariant, etc). So can explicit templates be "removed" from a C++/D-like language, and replaced by simpler generics, plus CTFE, plus a variable type (that is used at compile-time only by CTFE functions) that can contain a type? (Note that the end result is more or less the starting point. It's mostly a syntax shuffle). If I am not saying silly things, then the end result is a language with a semantics similar of D (it can do the same things), but with a little simpler syntax, because for the eyes of the programmer it contains functions only (plus classes, structs, etc). Bye, bearophile
Mar 14 2010
Sorry, missed a small piece: Walter Bright:Years ago, although I had implemented templates for C++, I didn't "get" them. Not at all.<This is incredible. Thank you for this information :-) Bye, bearophile
Mar 14 2010
On Sun, Mar 14, 2010 at 21:29, Walter Bright <newshound1 digitalmars.com>wrote:Philippe Sigaud wrote:That's interesting to know that you could implement templates, without understanding them. I eventually realized that what was preventing me from understanding C++1- thanks Walter for opening new vistas to me. Doing templated code in D is so fun and powerful that you transformed forever the way I look at problems.Years ago, although I had implemented templates for C++, I didn't "get" them. Not at all. I didn't even plan to put templates in D, because they seemed overly complex, ugly, and had little value.templates was the syntax. Change the syntax, and what is happening suddenly becomes obvious. (snip) Yes, it looks like a trivial change, and perhaps it is. But it makes a world of difference, because it now looks like something I do get - a parameter list to something.That's my first 15' with D right there, Walter. It may be due to my not knowing what 'template' means in English at the time I was exposed to them in C++. But reading the D docs, it became clear that they were just 'potential code', waiting to be created, with parameters governing what could happen.I had another epiphany from watching Scott Meyers give a presentation about an application for templated type lists in C++. Nearly the full hour was spent detailing a titanic struggle with the syntax. I suddenly realized that the whole presentation would have been over in 5 minutes if the syntax of type lists was simply that of an array of types. We already understand arrays of values, so why should an array of types be any different?Seconded, and thanks again for making that accessible. I was looking at Boost MPL (Meta-Programming Library) a few days ago, and thinking "How complicated the C++ syntax makes all this". I consider the MPL one of the most impressive part of Boost, but I don't think I'll ever use it. I have trouble extracting the intent among all the syntactic noise. Whereas in D, the first time I read some of Andrei's templates, (something akin to staticMap!(Unqual, Types)) the meaning was clear. The third 'leg' on which D templates rest is the alias parameters. I can have access to any symbol, including other templates? Oh yes! Philippe
Mar 14 2010
Philippe Sigaud wrote:Years ago, although I had implemented templates for C++, I didn't "get" them. Not at all. I didn't even plan to put templates in D, because they seemed overly complex, ugly, and had little value. That's interesting to know that you could implement templates, without understanding them.I think of it like a race car builder. I can build the cars, but I can't drive them worth squat. We are very fortunate, however, to have Andrei on board who literally wrote the book on how to drive them!The third 'leg' on which D templates rest is the alias parameters. I can have access to any symbol, including other templates? Oh yes!In C++, these are called "template template parameters". It took me a long time to figure out what the point to template template parameters was, and then I wondered at the arbitrary restriction that they must be templates. Remove the restriction, and voila! Much more power! (And a much simpler explanation of them, too.)
Mar 14 2010
======= C++ ========= template<class T> class Foo { T member; }; ======= D =========== class Foo(T) { T member; } ===================== Yes, it looks like a trivial change, and perhaps it is. But it makes a world of difference, because it now looks like something I do get - a parameter list to something.Fucking beautiful. I finally get it.I had another epiphany from watching Scott Meyers give a presentation about an application for templated type lists in C++. Nearly the full hour was spent detailing a titanic struggle with the syntax. I suddenly realized that the whole presentation would have been over in 5 minutes if the syntax of type lists was simply that of an array of types. We already understand arrays of values, so why should an array of types be any different? It isn't the concept or application of templates that is hard. It's the C++ syntax for them that's hard. It's hard in C++ because when they were designed, little was known or understood about what templates were good for and how they should be used. Now that we do know, we can make a much more straightforward design.They say you understand stuff only after you make it, not before.
Mar 14 2010
Bane wrote:Ya know what's funny? I had to go and double check that the C++ syntax above was correct. Didn't have to do that for D.======= C++ ========= template<class T> class Foo { T member; }; ======= D =========== class Foo(T) { T member; } ===================== Yes, it looks like a trivial change, and perhaps it is. But it makes a world of difference, because it now looks like something I do get - a parameter list to something.Fucking beautiful. I finally get it.
Mar 14 2010
Walter Bright Wrote:Bane wrote:D's example has look and feel of D, so it's intuitive. C++'s example may have l'n'f of C++, but it don't help because its ugly as crap by default and order of things in it make my eyes bleed and brain hurt. I hate <>. I like them only in XHTML.Ya know what's funny? I had to go and double check that the C++ syntax above was correct. Didn't have to do that for D.======= C++ ========= template<class T> class Foo { T member; }; ======= D =========== class Foo(T) { T member; } ===================== Yes, it looks like a trivial change, and perhaps it is. But it makes a world of difference, because it now looks like something I do get - a parameter list to something.Fucking beautiful. I finally get it.
Mar 15 2010
On 15.03.2010 3:42, Walter Bright wrote:Bane wrote:Though I love D's templates: 1. People tend to throw them in where a runtime solution would suffice. One example is an overload of 'clear' in the D runtime: void clear(T)(T obj) if (is(T == class)) { auto defaultCtor = cast(void function(Object)) obj.classinfo.defaultConstructor; version(none) // enforce isn't available in druntime _enforce(defaultCtor || (obj.classinfo.flags & 8) == 0); immutable size = obj.classinfo.init.length; static if (is(typeof(obj.__dtor()))) { obj.__dtor(); } auto buf = (cast(void*) obj)[0 .. size]; buf[] = obj.classinfo.init; if (defaultCtor) defaultCtor(obj); } Since the function uses runtime information (except for the destructor), it is absolutely unnecessary to instantiate the template for each concrete class type. A more severe problem with the code above, unrelated to templates, is that base class destructors are not called. Here is a non-template implementation that should fix the problems (it is a template but only formally): void clear(Dummy = void)(Object obj) { auto ci = obj.classinfo; auto defaultCtor = cast(void function(Object)) ci.defaultConstructor; version(none) // enforce isn't available in druntime _enforce(defaultCtor || (ci.flags & 8) == 0); immutable size = ci.init.length; auto ci2 = ci; do { auto dtor = cast(void function(Object))ci2.destructor;; if (dtor) dtor(obj); ci2 = ci2.base; } while (ci2) auto buf = (cast(void*) obj)[0 .. size]; buf[] = ci.init; if (defaultCtor) defaultCtor(obj); } BTW, I do think that base class destructor calls not compiled directly into derived class destructors is a mistake. 2. Templates impose functional style on programmers (see Bartosz's rant at http://bartoszmilewski.wordpress.com/2009/10/21/what-does-haskell-have-to-do-with-c/).Ya know what's funny? I had to go and double check that the C++ syntax above was correct. Didn't have to do that for D.======= C++ ========= template<class T> class Foo { T member; }; ======= D =========== class Foo(T) { T member; } ===================== Yes, it looks like a trivial change, and perhaps it is. But it makes a world of difference, because it now looks like something I do get - a parameter list to something.Fucking beautiful. I finally get it.
Mar 15 2010
Max Samukha wrote:Here is a non-template implementation that should fix the problems (it is a template but only formally):Thanks, I've incorporated it.
Mar 15 2010
Philippe Sigaud Wrote:Today I think in templates (well, at least I try to...). So: 1- thanks Walter for opening new vistas to me. Doing templated code in D is so fun and powerful that you transformed forever the way I look at problems. 2- Do other have a similar evolution?I started with a basic comfort with templates and generalizing code, but have taken things farther with D. I recently started ripping some templates out because my code was getting ugly. What I'm currently wishing for is templated modules... module foo(T,U,V); class bar // Implicit (T,U,V) { } module x; import foo!(T,U,V) bar b; // Not messier bar!(T,U,V) b It's a small bit of syntactic sugar, but for certain constructs, it can make a world of difference. I wonder if others would also want that.
Mar 14 2010
Jason House wrote:Philippe Sigaud Wrote:module foo; template foo(T,U,V) { ... your module's declarations ... } should do it.Today I think in templates (well, at least I try to...). So: 1- thanks Walter for opening new vistas to me. Doing templated code in D is so fun and powerful that you transformed forever the way I look at problems. 2- Do other have a similar evolution?I started with a basic comfort with templates and generalizing code, but have taken things farther with D. I recently started ripping some templates out because my code was getting ugly. What I'm currently wishing for is templated modules... module foo(T,U,V); class bar // Implicit (T,U,V) { } module x; import foo!(T,U,V) bar b; // Not messier bar!(T,U,V) b It's a small bit of syntactic sugar, but for certain constructs, it can make a world of difference. I wonder if others would also want that.
Mar 14 2010
Walter Bright Wrote:Max Samukha wrote:Thanks for that, but what about the other issues, why does this function have to be a template? Why does calling __dtor doesn't call base class destructors(as it is done in C++)?Here is a non-template implementation that should fix the problems (it is a template but only formally):Thanks, I've incorporated it.
Mar 15 2010
Eldar Insafutdinov wrote:Walter Bright Wrote:So it works with other types, though that isn't implemented.Max Samukha wrote:Thanks for that, but what about the other issues, why does this function have to be a template?Here is a non-template implementation that should fix the problems (it is a template but only formally):Thanks, I've incorporated it.Why does calling __dtor doesn't call base class destructors(as it is done in C++)?Doing it that way is non-trivial, and I was in a hurry to get the system working. Class destructors are rarely used in D, so doing it the simple way is not a performance issue. Destructors for structs, however, are done the more complicated (and more performant) way because they need to be more efficient.
Mar 15 2010
Walter Bright Wrote:Eldar Insafutdinov wrote:This code: ------- void clear(Dummy = void)(Object obj) { pragma(msg, "template instance: Object clear"); } void clear(T)(ref T obj) if (!is(T == class)) { pragma(msg, "template instance: " ~ T.stringof ~ " clear"); } class Boo {} class Foo {} struct Bar {} struct Baz {} void main() { auto boo = new Boo; auto foo = new Foo; Bar bar; Baz baz; clear(boo); clear(foo); clear(bar); clear(baz); } ------- outputs during compilation: template instance: Object clear template instance: Bar clear template instance: Baz clear Isn't that what you need?Walter Bright Wrote:So it works with other types, though that isn't implemented.Max Samukha wrote:Thanks for that, but what about the other issues, why does this function have to be a template?Here is a non-template implementation that should fix the problems (it is a template but only formally):Thanks, I've incorporated it.Thanks for the clarification. This is something I know little about, so I can't argue here.Why does calling __dtor doesn't call base class destructors(as it is done in C++)?Doing it that way is non-trivial, and I was in a hurry to get the system working. Class destructors are rarely used in D, so doing it the simple way is not a performance issue. Destructors for structs, however, are done the more complicated (and more performant) way because they need to be more efficient.
Mar 15 2010