www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Understanding Templates: why can't anybody do it?

reply "Entity325" <lonewolf325 gmail.com> writes:
(Sorry if this is the wrong place for this, or if there's already 
a thread in existence which would be better.  If either of these 
is the case, simply point me in the right direction, and I'll be 
on my way.)

My first interaction with Templates was about 5 years ago, in a 
C++ class at my university.  I immediately thought "A general 
type?  This would be great for my logger!" and tried to implement 
them into the small library I had been developing to save time on 
the class assignments.

Naturally, I didn't understand them, so after a couple of 
half-hearted attempts, I gave up and went back to doing things 
the way I had before.  I've avoided Templates since then, because 
they don't make any sense!

5 years later, enter D.  In the process of trying to teach myself 
some D, I've found myself with a library of Structs for which the 
operator overloading features are extremely handy.

Teensy problem here: the documentation on how to use operators 
makes use of Template types in the examples.

Having developed a bit more analytical skill and tenacity in the 
intervening years, I resolved to actually figure the mess out 
this time.  I have come to a conclusion.

The reason nobody understands Templates is that nobody 
understands them.

That is to say, nobody understands how Templates work is because, 
as was the case for me, the sum total of explanation we are given 
on them in programming class is "These are Templates.  They 
exist.  They look something like this."

Even the (quite thorough) documentation for the D language 
reference isn't immune to this, if we take a look.  
(http://dlang.org/template.html) As you can see, the page more or 
less starts off with "--And here are some cool things you can do 
with templates."

Wait, what?  I feel like I've started watching Primer 20 minutes 
before the end, without anybody telling me what's going on.

Herein, I think, lies the root of the reason why nobody 
understands Templates.  I think the solution to this problem is 
not to comfort programming students by saying "Don't worry, 
nobody understands Templates."  I think it's time we collectively 
figured out what they are.  That done, we can overhaul the way 
new programmers learn how to use them.

Who's with me?  Anybody have a short(but COMPLETE!) example of 
code that makes use of Templates that you actually understand 
what's going on there?
Mar 17 2012
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 3/17/12 12:14 PM, Entity325 wrote:
 Who's with me? Anybody have a short(but COMPLETE!) example of code that
 makes use of Templates that you actually understand what's going on there?
You're on to something here. Then, as usual, from idea to realization there are quite a few steps. I took a complementary approach in TDPL: there's no chapter on templates at all. Templates are naturally interwoven with whatever topic is at hand, wherever they're useful. I hoped people would learn templates without even knowing it. Andrei
Mar 17 2012
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 3/17/2012 10:55 AM, Andrei Alexandrescu wrote:
 On 3/17/12 12:14 PM, Entity325 wrote:
 Who's with me? Anybody have a short(but COMPLETE!) example of code that
 makes use of Templates that you actually understand what's going on there?
You're on to something here. Then, as usual, from idea to realization there are quite a few steps. I took a complementary approach in TDPL: there's no chapter on templates at all. Templates are naturally interwoven with whatever topic is at hand, wherever they're useful. I hoped people would learn templates without even knowing it.
Sans value parameters: int foo() { return 3; } With value parameters: int foo(int i) { return i; } Sans type parameters: struct S { int i; } With type parameters: struct S(T) { T i; } i.e. templates are type parameters.
Mar 17 2012
parent reply "Xinok" <xinok live.com> writes:
On Saturday, 17 March 2012 at 18:16:31 UTC, Walter Bright wrote:
 i.e. templates are type parameters.
Maybe in C++. In C++, templates are attached to a class or function, where as in D, they're an independent construct. The way I think of it, templates are a tool for building static code from a set of parameters. String mixins are a similar tool which are more powerful but less elegant. Programmers will use templates for unintended purposes, but that doesn't change what they are. You can use full closures to store references to variables, but that doesn't make functions reference types.
Mar 17 2012
parent "novice2" <sorry noem.ail> writes:
 templates are a tool for building static code from a set of 
 parameters.
unfortunately (imho), there is no way to see the result code
Mar 17 2012
prev sibling next sibling parent Paulo Pinto <pjmlp progtools.org> writes:
Maybe you should first try to learn some concepts about generic programming

http://en.wikipedia.org/wiki/Generic_programming

You will see this is nothing specific to C++ or D, and almost
all modern languages do have some form of genericity.

If you still cannot understand them, you cold try to explain why
you have difficulties understanding this concept, and we could
try to explain them to you. Even improve D's documentation.

--
Paulo

Am 17.03.2012 18:14, schrieb Entity325:
 (Sorry if this is the wrong place for this, or if there's already a
 thread in existence which would be better. If either of these is the
 case, simply point me in the right direction, and I'll be on my way.)

 My first interaction with Templates was about 5 years ago, in a C++
 class at my university. I immediately thought "A general type? This
 would be great for my logger!" and tried to implement them into the
 small library I had been developing to save time on the class assignments.

 Naturally, I didn't understand them, so after a couple of half-hearted
 attempts, I gave up and went back to doing things the way I had before.
 I've avoided Templates since then, because they don't make any sense!

 5 years later, enter D. In the process of trying to teach myself some D,
 I've found myself with a library of Structs for which the operator
 overloading features are extremely handy.

 Teensy problem here: the documentation on how to use operators makes use
 of Template types in the examples.

 Having developed a bit more analytical skill and tenacity in the
 intervening years, I resolved to actually figure the mess out this time.
 I have come to a conclusion.

 The reason nobody understands Templates is that nobody understands them.

 That is to say, nobody understands how Templates work is because, as was
 the case for me, the sum total of explanation we are given on them in
 programming class is "These are Templates. They exist. They look
 something like this."

 Even the (quite thorough) documentation for the D language reference
 isn't immune to this, if we take a look.
 (http://dlang.org/template.html) As you can see, the page more or less
 starts off with "--And here are some cool things you can do with
 templates."

 Wait, what? I feel like I've started watching Primer 20 minutes before
 the end, without anybody telling me what's going on.

 Herein, I think, lies the root of the reason why nobody understands
 Templates. I think the solution to this problem is not to comfort
 programming students by saying "Don't worry, nobody understands
 Templates." I think it's time we collectively figured out what they are.
 That done, we can overhaul the way new programmers learn how to use them.

 Who's with me? Anybody have a short(but COMPLETE!) example of code that
 makes use of Templates that you actually understand what's going on there?
Mar 17 2012
prev sibling next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/17/2012 10:14 AM, Entity325 wrote:

 Who's with me? Anybody have a short(but COMPLETE!) example of code that
 makes use of Templates that you actually understand what's going on 
there? The "Templates" chapter of "Programming in D" is supposed to be a gentle introduction to templates: http://ddili.org/ders/d.en/templates.html The book have supposed to build up enough base in the previous chapters to make the topic easy to follow but some of the previous chapters have not been translated to English yet. There is a second templates chapter later in the book that covers to-me more advanced features, which also has not been translated yet. Please provide feedback. :) The chapter also contains a link to Philippe Sigaud's "D Templates: A Tutorial". Ali
Mar 17 2012
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/17/2012 12:57 PM, Ali Çehreli wrote:

 http://ddili.org/ders/d.en/templates.html
[...]
 The chapter also contains a link to Philippe Sigaud's "D Templates: A
 Tutorial".
Sorry, I did not intend to leave the link to that document out: https://github.com/PhilippeSigaud/D-templates-tutorial/blob/master/dtemplates.pdf Ali
Mar 17 2012
prev sibling next sibling parent Max Klyga <max.klyga gmail.com> writes:
On 2012-03-17 20:14:47 +0300, Entity325 said:
 Who's with me?  Anybody have a short(but COMPLETE!) example of code 
 that makes use of Templates that you actually understand what's going 
 on there?
Philippe Sigaud made a very good tutorial on templates in D - https://github.com/PhilippeSigaud/D-templates-tutorial/raw/m ster/dtemplates.pdf
Mar 17 2012
prev sibling next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Entity325" <lonewolf325 gmail.com> wrote in message 
news:pgzkvphadihglayfulij forum.dlang.org...
 That is to say, nobody understands how Templates work is because, as was 
 the case for me, the sum total of explanation we are given on them in 
 programming class is "These are Templates.  They exist.  They look 
 something like this."
I've spent a total of about 6 years in college, always got A's and B's in the CS classes, and yet I'm convinced that programming classes are completely and utterly useless. Most of the instructors themselves barely even know how to code (among many, many other problems). So if you're learning programming at college, then I'm not surprised you've gotten the impression that nobody understands templates: Around universities, they probably don't. (Also, it doesn't help that C++'s templates could be a lot better.) I even had one CS prof, he said that the only language he knew was C. And yet, after seeing his feedback on my code, it became abundantly clear to me that he didn't even understand how strings worked (ie: C's famous null-terminated strings) *in the ONE language he knew*. Here's a little templates primer, I hope it helps: A template is just clean way of generating code instead of manually copy-pasting a bunch of times (which would end up being a maintenance nightmare). Suppose you have this: int add(int a, int b) { return a + b; } Call it, of course, like this: add(7, 42); And then you want another version that does it with doubles: double add(double a, double b) { return a + b; } Called, of course, like this: add(3.14, 5.73); Now you've got two copies that are exactly the same thing, just with one little thing changed. If you need top modify one, you'll have to remember to modify the other too. And god help you if it's a really big function and you accidentally make a mistake copying it. It just gets to be a big problem. It violates what we call DRY: "Don't Repeat Yourself". Let's step back into first grade for a minute: Have you ever drawn or painted with stencils? You make one design, once, by cutting it out of paper. Then you can easily draw and re-draw the same design with different colors: Just place the stencil on a new piece of paper, choose a color, color it, lift the stencil, and there's another copy of your design, but in whatever different color you wanted. Templates are stencils for code. Heck, even outside of code this is true too. "template" is just another word for "stencil". So here's how you make an "add() function" stencil. Just "punch out" what you want to change, by making it a template parameter: // Make a "stencil" template myTemplate(T) { // This is what's in the "stencil" T add(T a, T b) { return a + b; } } Notice how the add() function is exactly the same as before, but the "int"s were changed to "T" (for "Type"). Let's stamp down some "add()" prints: // The dot in between is because "add" is *inside* the template "myTemplate" myTemplate!(int).add(7, 42); myTemplate!(double).add(3.14, 5.73); Notice how that's exactly the same as before, but I have that "myTemplate!(int)", and another with "float". The compiler turns that into: int add(int a, int b) { return a + b; } add(7, 42); double add(double a, double b) { return a + b; } add(3.14, 5.73); Suppose now we also want to be able to use add() for ulong and BigInt. Instead of manually copying the function and changing the type, we can just let the *compiler* copy the function and change the type: myTemplate!(ulong).add(7, 42); myTemplate!(BigInt).add(BigInt(7), BigInt(42)); The compiler, of course, automatically generates: ulong add(ulong a, ulong b) { return a + b; } BigInt add(BigInt a, BigInt b) { return a + b; } And then calls them: add(7, 42); add(BigInt(7), BigInt(42)); You can also add more stuff to the template: // A bigger "stencil" template myTemplate(T) { T add(T a, T b) { return a + b; } T mult(T a, T b) { return a * b; } } So now the compiler will turn this: myTemplate!(int) myTemplate!(double) Into this: int add(int a, int b) { return a + b; } int mult(int a, int b) { return a * b; } double add(double a, double b) { return a + b; } double mult(double a, double b) { return a * b; } And you can use them like this: myTemplate!(int).add(7, 42); myTemplate!(double).add(3.14, 5.73); myTemplate!(int).mult(7, 42); myTemplate!(double).mult(3.14, 5.73); You can put other things inside the template, too, like structs and classes, or even variables: template anotherTemplate(T, int initialValue) { struct Foo { T value; int someInt = initialValue; } T[] myArray; } // Use the array: anotherTemplate!(string, 5).myArray = ["abc", "def", "g"]; // Declare a variable "myFoo" of type "Foo": // Foo's "value" should be a string // And Foo's "someInt" should start out as 5 anotherTemplate!(string, 5).Foo myFoo; if(myFoo.someInt == 5) myFoo.value = "Hello"; D has some convenient tricks though: Using that "myTemplate" and "anotherTemplate" all over is a bit of a bother. Why should we have to? D has a shortcut for making and using templates: T add(T)(T a, T b) { return a + b; } That's nothing more than a convenient shortcut for: template add(T) { T add(T a, T b) { return a + b; } } Or the struct: struct Foo(T, int initialValue) { T value; int someInt = initialValue; } Which is a convenient shortcut for: template Foo(T, int initialValue) { struct Foo { T value; int someInt = initialValue; } } The same trick doesn't work for variables like myArray though, you'll have to manually write them as: template myArray(T) { T[] myArray; } Here's another nice trick: Since the name of the template and the "thing" inside the template is the same, you don't have to repeat them. All you have to write is: add!int(7, 42); add!double(3.14, 5.73); add!BigInt(BigInt(7), BigInt(42)); mult!int(7, 42); mult!double(3.14, 5.73); mult!BigInt(BigInt(7), BigInt(42)); myArray!string = ["abc", "def", "g"]; myArray!int = [1, 2, 3]; myArray!double = [1.5, 2.70, 3.14]; Foo!(string, 5) myFoo; if(myFoo.someInt == 5) myFoo.value = "Hello"; Foo!(float, 1) bar; if(bar.someInt == 1) bar.value = 3.14; And there's yet one more convenience: A special thing D has called IFTI: Implicit Function Template Instantiation. Yes, it sounds very intimidating, but it's really very easy. D lets you call the functions above like this: add(7, 42); add(3.14, 5.73); add(BigInt(7), BigInt(42)); mult(7, 42); mult(3.14, 5.73); mult(BigInt(7), BigInt(42)); Look ma! No types! D already knows that 7 and 43 are int, so it automatically uses the "add!int" version. D already knows that 3.14 and 5.73 are double, so it automatically uses the "add!double" version. D already knows that BigInt(7) and BigInt(42) are BigInt, so it automatically uses the "add!BigInt" version. So, we've started with this copy-paste mess: int add(int a, int b) { return a + b; } double add(double a, double b) { return a + b; } add(7, 42); add(3.14, 5.73); add(BigInt(7), BigInt(42)); // ERROR! You didn't write a BigInt version! And turned it into this: T add(T)(T a, T b) { return a + b; } add(7, 42); add(3.14, 5.73); add(BigInt(7), BigInt(42)); add( /+ anything else! +/ ); Which automatically stamps out any "add()" function you need, when you need it. And we can do the same for structs, classes and variables.
Mar 17 2012
next sibling parent reply "novice2" <sorry noem.ail> writes:
How it come, that we build another abstartion level above strong 
typed language?
Onece we builded high level language above assembler. Are we now 
building another more high level? Will temlate will become 
another language used as complete language? Will generic 
prigramming become mainstream, like high level languages today?
Mar 17 2012
next sibling parent reply =?utf-8?Q?Simen_Kj=C3=A6r=C3=A5s?= <simen.kjaras gmail.com> writes:
On Sat, 17 Mar 2012 21:56:14 +0100, novice2 <sorry noem.ail> wrote:

 How it come, that we build another abstartion level above strong typed  
 language?
 Onece we builded high level language above assembler. Are we now  
 building another more high level? Will temlate will become another  
 language used as complete language? Will generic prigramming become  
 mainstream, like high level languages today?
It seems to me that templates are mostly useful for libraries. In user code this flexibility is rarely as useful. It may however be that this very same argument was put forth when OO was introduced.
Mar 17 2012
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sat, Mar 17, 2012 at 10:15:26PM +0100, Simen Kjærås wrote:
 On Sat, 17 Mar 2012 21:56:14 +0100, novice2 <sorry noem.ail> wrote:
 
How it come, that we build another abstartion level above strong
typed language?
Onece we builded high level language above assembler. Are we now
building another more high level? Will temlate will become another
language used as complete language? Will generic prigramming
become mainstream, like high level languages today?
It seems to me that templates are mostly useful for libraries. In user code this flexibility is rarely as useful. It may however be that this very same argument was put forth when OO was introduced.
I disagree. I use templates all the time, in my own code. It's a great way to factor out common code, so that you avoid code duplication (which often also means bug duplication). For example, I'm writing a grid-based game, where I have a Board class that stores an array of tiles representing game pieces. For various reasons (not relevant here), I decided I should store the tiles as a linear array, and just overload opIndex() to provide "2D access": class Board { Tile[] tiles; int width, height; Tile opIndex(int x, int y) { return tile[offsetOf(x,y)]; } private int offsetOf(int x, int y) in { assert(x>=0 && x<width && y>=0 && y<height); } out(z) { assert(z>=0 && z<tiles.length); } body { return x + y*width; } } Later on, after I've implemented a working game, I decide to make the AI player a bit smarter. For that, I decided to have the AI precompute optimal movement paths by assigning an integer to each tile, and then scanning the board to find optimal paths based on the ints assigned to each tile. I *could* add an int to Tile and use that, but the problem is, they are only used during the pre-game computation by the AI; the computed paths are stored separately after this computation is done, so the integers are not needed during the actual gameplay. So storing the ints in Tile is a waste of space. So what I really need is a Board that stores ints instead of Tiles. But the current Board class is already bound to Tile's! What can I do? Aha! I can make Board a template: class Board(T) { T[] tiles; int width, height; T opIndex(int x, int y) { ... } ... } Then for the actual game board, I'd have: Board!Tile gameboard; And for the AI's precomputed data, I'd have: Board!int aidata; After the AI has found the optimal paths, I can discard aidata and continue using gameboard. Situations like this arise quite often in my code. So I'd say that templates are definitely not limited to library code. They are generally applicable. T -- Famous last words: I *think* this will work...
Mar 17 2012
prev sibling next sibling parent reply Paulo Pinto <pjmlp progtools.org> writes:
Am 17.03.2012 21:56, schrieb novice2:
 How it come, that we build another abstartion level above strong typed
 language?
 Onece we builded high level language above assembler. Are we now
 building another more high level? Will temlate will become another
 language used as complete language? Will generic prigramming become
 mainstream, like high level languages today?
Generic programming is already mainstream. are just a few of the current languages that support generic programming. -- Paulo
Mar 17 2012
parent reply =?utf-8?Q?Simen_Kj=C3=A6r=C3=A5s?= <simen.kjaras gmail.com> writes:
On Sat, 17 Mar 2012 22:16:37 +0100, Paulo Pinto <pjmlp progtools.org>  
wrote:

 Am 17.03.2012 21:56, schrieb novice2:
 How it come, that we build another abstartion level above strong typed
 language?
 Onece we builded high level language above assembler. Are we now
 building another more high level? Will temlate will become another
 language used as complete language? Will generic prigramming become
 mainstream, like high level languages today?
Generic programming is already mainstream. are just a few of the current languages that support generic programming.
The languages support it. The hard part is getting programmers to use it.
Mar 17 2012
parent Paulo Pinto <pjmlp progtools.org> writes:
Am 17.03.2012 22:19, schrieb Simen Kjærås:
 On Sat, 17 Mar 2012 22:16:37 +0100, Paulo Pinto <pjmlp progtools.org>
 wrote:

 Am 17.03.2012 21:56, schrieb novice2:
 How it come, that we build another abstartion level above strong typed
 language?
 Onece we builded high level language above assembler. Are we now
 building another more high level? Will temlate will become another
 language used as complete language? Will generic prigramming become
 mainstream, like high level languages today?
Generic programming is already mainstream. Eiffel are just a few of the current languages that support generic programming.
The languages support it. The hard part is getting programmers to use it.
I agree 100% with you. Still I would like to remark, that at least from my work colleagues, the ones with problems to make proper use of algorithms and abstractions, are the ones without CS background.
Mar 17 2012
prev sibling parent "Nick Sabalausky" <a a.a> writes:
"novice2" <sorry noem.ail> wrote in message 
news:hzbmfpsyzezjwzshxjsp forum.dlang.org...
 How it come, that we build another abstartion level above strong typed 
 language?
 Onece we builded high level language above assembler. Are we now building 
 another more high level? Will temlate will become another language used as 
 complete language? Will generic prigramming become mainstream, like high 
 level languages today?
It's really just another tool in the toolbox. Like OO. And there's always more abstractions on top of abstractions: High-level langauges are an abstration on top of low-level. Low level programming is an abstration on top of digital hardware. Digital hardware is an abstraction on top of analog hardware. Analog hardware is an abstraction on top of chemistry. Chemistry is an abstration on top of natural observations of interacting with various materials. Observations are an abstraction on top of our perceptions of reality and sensory input. First we discover useful things to do with one abstraction. Then we make use of that abstraction to the point where it starts to get complex. So we look for patterns in the complexity and use those patterns as the foundation for a new abstraction to make these complicated new things simple. And it starts again. Sending a link to a document across the world is trivial today, but it would be unthinkably complex without the abstractions of high level code, low level code, digital hardware, etc.
Mar 17 2012
prev sibling next sibling parent reply Paulo Pinto <pjmlp progtools.org> writes:
Am 17.03.2012 21:20, schrieb Nick Sabalausky:
 "Entity325"<lonewolf325 gmail.com>  wrote in message
 news:pgzkvphadihglayfulij forum.dlang.org...
 That is to say, nobody understands how Templates work is because, as was
 the case for me, the sum total of explanation we are given on them in
 programming class is "These are Templates.  They exist.  They look
 something like this."
I've spent a total of about 6 years in college, always got A's and B's in the CS classes, and yet I'm convinced that programming classes are completely and utterly useless. Most of the instructors themselves barely even know how to code (among many, many other problems). So if you're learning programming at college, then I'm not surprised you've gotten the impression that nobody understands templates: Around universities, they probably don't. (Also, it doesn't help that C++'s templates could be a lot better.) I even had one CS prof, he said that the only language he knew was C. And yet, after seeing his feedback on my code, it became abundantly clear to me that he didn't even understand how strings worked (ie: C's famous null-terminated strings) *in the ONE language he knew*.
I would say that most European universities seem to provide a completely different experience, at least speaking from my experience in Portuguese/Swiss/German ones.
Mar 17 2012
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sat, Mar 17, 2012 at 10:13:44PM +0100, Paulo Pinto wrote:
 Am 17.03.2012 21:20, schrieb Nick Sabalausky:
[...]
I've spent a total of about 6 years in college, always got A's and
B's in the CS classes, and yet I'm convinced that programming classes
are completely and utterly useless. Most of the instructors
themselves barely even know how to code (among many, many other
problems). So if you're learning programming at college, then I'm not
surprised you've gotten the impression that nobody understands
templates: Around universities, they probably don't. (Also, it
doesn't help that C++'s templates could be a lot better.)

I even had one CS prof, he said that the only language he knew was C.
And yet, after seeing his feedback on my code, it became abundantly
clear to me that he didn't even understand how strings worked (ie:
C's famous null-terminated strings) *in the ONE language he knew*.
I would say that most European universities seem to provide a completely different experience, at least speaking from my experience in Portuguese/Swiss/German ones.
[...] My experience in a Canadian university wasn't quite that bad either. True, there *were* some courses where the profs don't really care about teaching, or where they're so self-absorbed that you can barely even begin to understand where their sentences start and end, let alone understand what they're trying to say. But I did have quite a few good programming classes, notably one that got me started off with C, and another that got me started with C++. Of course, I also learned a lot more stuff about C/C++ that wasn't taught in class, but then you can hardly expect the prof to teach you *everything* there is to know about C/C++. After all, you're expected to be an adult by then, and theoretically you'd know how to learn more on your own. Anyway. Coming back to templates, I think Nick did an excellent job at explaining them. When learning something new in programming, I always like to ask, why is feature X this way? What is it used for? Why did people invent such a thing in the first place? What was the motivation behind it? What does it solve? What's so good about them that I have to learn this? Templates are the result of a long history of trying to minimize the amount of code you have to write/change when all you want is to add some new data to existing code. Suppose you have a program that needs to keep track of a list of integers, say. There are, of course, many ways of doing this, but suppose you chose to implement it as a linked list. So you write something like this: class Node { Node next; int data; } class LinkedList { Node head; Node tail; void add(int data) { Node n = new Node; n.data = data; ... // insert node into list } void del(int data) { ... } } So far so good. But what if later on, you realize that you need to store not just an int, but also a float as well? So you'd have to go through all that code, and add a new field wherever it's needed: class Node { Node next; int intdata; float floatdata; } class LinkedList { Node head; Node tail; void add(int idata, float fdata) { Node n = new Node; n.intdata = idata; n.floatdata = fdata; ... // insert node into list } void del(int data, float fdata) { ... } } OK, that's a lot of code changes for something as simple as adding a single field to your list nodes. What if you need a string next? You have to go through the entire code and insert string fields and string arguments everywhere. And what if you need something else after that? Again, you have to go through all your code and update everything. (And perhaps miss a few places, causing subtle bugs to creep into your program.) We can do better. We can encapsulate the data inside a separate struct so that we don't have to keep changing Node and LinkedList every time we need to store new data: struct Data { int intdata; float floatdata; } class Node { Node next; Data data; // ahhh, much better! } class LinkedList { Node head; Node tail; void add(Data d) { Node n = new Node; n.data = d; ... // insert node into list } void del(Data d) { ... } } Now, what if we need to add a string into our list of data? No problem, just add a single line to struct Data: struct Data { int intdata; float floatdata; string strdata; } See how you don't have to change Node and LinkedList at all? That's good, because you may have spent hours debugging the linked list code, and so not making any more changes ensures no new bugs will be introduced. Plus you've saved yourself a lot of work going through everything to add the new field. So far so good. But what if you need *another* list? Say, a list that stores a different kind of data? You can't change struct Data, because you still need to use it in the earlier part of the program. So you'd have to write the code all over again, except with a different struct: struct OtherData { int x,y,z; } class OtherNode { OtherNode next; OtherData data; } class OtherLinkedList { OtherNode head; OtherNode tail; void add(OtherData d) { OtherNode n = new OtherNode; n.data = d; ... // insert node into list } void del(OtherData d) { ... } } Wait a minute here! This code looks identical to the previous code, except that the contents of the struct is different, and Node is renamed to OtherNode, Data is renamed to OtherData, etc.. The algorithms for adding/removing nodes from the linked list is exactly the same, except that a different kind of data is being passed around. Do we *really* have to duplicate the entire linked list code just so we can support two kinds of linked list? If you think about it, there's nothing about the concept of a linked list that is specifically tied to Data or OtherData. A linked list is simply a linked list; it's a sequences of nodes that contain data. What that data is, is irrelevant. The way you add a node to a linked list that contains Data is exactly the same way you add a node to a linked list that contains OtherData. So Node and LinkedList really shouldn't be tied to Data or OtherData at all. This is where templates come in. It allows us to say, a linked list consists of nodes linked to each other in a chain, and stores some kind of data X, but what X is, is decided by the code elsewhere; it's not important to the linked list itself. Here's how you use templates to do this: class Node(X) { Node next; X d; } class LinkedList(X) { Node!X head; Node!X tail; void add(X data) { Node!X n = new Node!X(); n.d = data; ... // insert node into list } void del(X data) { ... } } Looks familiar? It looks just like our code from before, except that now the symbol X is not bound to any particular thing. For example, to create a linked list for storing struct Data, we can do this: LinkedList!Data datalist; When you write this, the compiler substitutes Data for X, and then automatically replaces all instances of X in the definition of Node and LinkedList with "Data". So this gives us a list identical to the one we wrote at first. What about when we need to store OtherData? Now we don't have to duplicate the entire linked list code, we just write: LinkedList!OtherData otherlist; And the compiler automatically substitutes OtherData for all occurrences of X in Node and LinkedList. So it effectively "copy-n-paste"s the linked list code, just like we did by hand in the second example, except that it's now automatic. What if we want a linked list that stores string? Easy: LinkedList!string strlist; A linked list that stores doubles? No problem: LinkedList!double dlist; What about a linked list that stores linked lists? This would give you a nasty headache if you had to implement it by hand. You'd have to go through the linked list code, figure out which code applies to the sublists, and which code applies to the main list, and in all likelihood you'll end up with many pages of code full of bugs everywhere, because it's just too complicated. But this is no problem at all with templates. Here's a linked list that stores linked lists of ints: LinkedList!(LinkedList!int) nestedlist; And here's a linked list that stores linked lists of Data: LinkedList!(LinkedList!Data) nestedlist; The compiler automatically does the parameter substitution and embedding the lists inside each other. We only need to write a single line of code. Instead of 200 lines of code (and 199 bugs). This is the basic idea behind templates. Of course, templates can do a lot more than just make it easy to implement data structures. Now that we know the compiler can substitute template parameters, we can teach it to do a lot more tricks. But this should give you the basic motivations behind why we should have such things as templates, and why they are useful. T -- It is of the new things that men tire --- of fashions and proposals and improvements and change. It is the old things that startle and intoxicate. It is the old things that are young. -- G.K. Chesterton
Mar 17 2012
prev sibling next sibling parent reply =?utf-8?Q?Simen_Kj=C3=A6r=C3=A5s?= <simen.kjaras gmail.com> writes:
On Sat, 17 Mar 2012 21:20:42 +0100, Nick Sabalausky <a a.a> wrote:

 I've spent a total of about 6 years in college, always got A's and B's in
 the CS classes, and yet I'm convinced that programming classes are
 completely and utterly useless. Most of the instructors themselves barely
 even know how to code (among many, many other problems). So if you're
 learning programming at college, then I'm not surprised you've gotten the
 impression that nobody understands templates: Around universities, they
 probably don't. (Also, it doesn't help that C++'s templates could be a  
 lot better.)

 I even had one CS prof, he said that the only language he knew was C. And
 yet, after seeing his feedback on my code, it became abundantly clear to  
 me that he didn't even understand how strings worked (ie: C's famous
 null-terminated strings) *in the ONE language he knew*.
You seem to be harping on this a lot. My experience has been that programming teachers generally know what they're doing, but they're not exactly experts. Then again, like Paulo said, this might be a european phenomenon.
Mar 17 2012
parent "Nick Sabalausky" <a a.a> writes:
"Simen Kjærås" <simen.kjaras gmail.com> wrote in message 
news:op.wbb24i010gpyof biotronic.lan...
 On Sat, 17 Mar 2012 21:20:42 +0100, Nick Sabalausky <a a.a> wrote:

 I've spent a total of about 6 years in college, always got A's and B's in
 the CS classes, and yet I'm convinced that programming classes are
 completely and utterly useless. Most of the instructors themselves barely
 even know how to code (among many, many other problems). So if you're
 learning programming at college, then I'm not surprised you've gotten the
 impression that nobody understands templates: Around universities, they
 probably don't. (Also, it doesn't help that C++'s templates could be a 
 lot better.)

 I even had one CS prof, he said that the only language he knew was C. And
 yet, after seeing his feedback on my code, it became abundantly clear to 
 me that he didn't even understand how strings worked (ie: C's famous
 null-terminated strings) *in the ONE language he knew*.
You seem to be harping on this a lot.
Sorry. I definitely *do* have a big chip on my shoulder on the matter.
Mar 17 2012
prev sibling next sibling parent Jos van Uden <user domain.invalid> writes:
On 17-3-2012 21:20, Nick Sabalausky wrote:

 Here's a little templates primer, I hope it helps:
[...] Part of this primer would serve well as introduction to Phillipe's tutorial, because it skips the basics. (I knew the basics, but not everybody does.) Jos
Mar 17 2012
prev sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Nick Sabalausky" <a a.a> wrote in message 
news:jk2ro7$6dl$1 digitalmars.com...
 Here's a little templates primer, I hope it helps:

 [...]
I've cleaned this up, added an intro and outro, and posted it on my website here: https://www.semitwist.com/articles/article/view/template-primer-in-d
Mar 22 2012
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Fri, Mar 23, 2012 at 01:16:13AM -0400, Nick Sabalausky wrote:
 "Nick Sabalausky" <a a.a> wrote in message 
 news:jk2ro7$6dl$1 digitalmars.com...
 Here's a little templates primer, I hope it helps:

 [...]
I've cleaned this up, added an intro and outro, and posted it on my website here: https://www.semitwist.com/articles/article/view/template-primer-in-d
[...] +1. Good introduction to D templates. Pity you didn't get into fancy stuff like recursive templates, but I suppose that's out of the scope of an intro. :-) T -- Those who've learned LaTeX swear by it. Those who are learning LaTeX swear at it. -- Pete Bleackley
Mar 22 2012
parent reply "Nick Sabalausky" <a a.a> writes:
"H. S. Teoh" <hsteoh quickfur.ath.cx> wrote in message 
news:mailman.1037.1332480633.4860.digitalmars-d puremagic.com...
 On Fri, Mar 23, 2012 at 01:16:13AM -0400, Nick Sabalausky wrote:
 "Nick Sabalausky" <a a.a> wrote in message
 news:jk2ro7$6dl$1 digitalmars.com...
 Here's a little templates primer, I hope it helps:

 [...]
I've cleaned this up, added an intro and outro, and posted it on my website here: https://www.semitwist.com/articles/article/view/template-primer-in-d
[...] +1. Good introduction to D templates.
Thanks :)
 Pity you didn't get into fancy stuff like recursive templates, but I
 suppose that's out of the scope of an intro. :-)
Yea. Just kind of a "So what are these 'template' things anyway?" And some of that fancier template stuff (like template fibonacci) is better done as CTFE anyway ;)
Mar 22 2012
parent Sean Kelly <sean invisibleduck.org> writes:
On Mar 22, 2012, at 10:35 PM, Nick Sabalausky wrote:
=20
 And some of that fancier template stuff (like template fibonacci) is =
better=20
 done as CTFE anyway ;)
It is, but I think it should be covered anyway because people may still = encounter this code and should be able to grasp what it's doing.=
Mar 23 2012
prev sibling parent Sean Kelly <sean invisibleduck.org> writes:
On Mar 22, 2012, at 10:31 PM, H. S. Teoh wrote:

 On Fri, Mar 23, 2012 at 01:16:13AM -0400, Nick Sabalausky wrote:
 "Nick Sabalausky" <a a.a> wrote in message=20
 news:jk2ro7$6dl$1 digitalmars.com...
=20
 Here's a little templates primer, I hope it helps:
=20
 [...]
=20 I've cleaned this up, added an intro and outro, and posted it on my website here: =20 https://www.semitwist.com/articles/article/view/template-primer-in-d
[...] =20 +1. Good introduction to D templates. =20 Pity you didn't get into fancy stuff like recursive templates, but I suppose that's out of the scope of an intro. :-)
The chapter on templates in Learn to Tango with D gets into the basics = of template metaprogramming, but in article form it would probably be = part 3 of a series. I think that chapter is ~20 pages long.=
Mar 23 2012
prev sibling next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 3/17/12, Entity325 <lonewolf325 gmail.com> wrote:
 Who's with me?  Anybody have a short(but COMPLETE!) example of
 code that makes use of Templates that you actually understand
 what's going on there?
I wrote this a long time ago when I was just figuring out what templates were about (it's not a general-purpose template tutorial but just an explanation of a Phobos templated function that someone was curious about): http://prowiki.org/wiki4d/wiki.cgi?D__Tutorial/D2Templates I had no idea what templates were when I started using D, and I thought I would never need to use them either. But now I use them extensively. They really become a natural tool in programming. They're so nice to use that I never have to reach for the big fat OOP monster, I can just write simple procedural code and use templates when I need some flexibility. In the meantime people have written some pretty good tutorials, like Ali =C7ehreli's chapter on templates, and recently Philippe Sigaud's D Template book. Those should be good resources on templates.
Mar 17 2012
parent reply Gour <gour atmarama.net> writes:
On Sat, 17 Mar 2012 21:29:18 +0100
Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:

 I had no idea what templates were when I started using D, and I
 thought I would never need to use them either. But now I use them
 extensively. They really become a natural tool in programming. They're
 so nice to use that I never have to reach for the big fat OOP monster,
 I can just write simple procedural code and use templates when I need
 some flexibility.
Thank you for this paragraph. ;) I also consider to write procedural/functional code in my project and leave OOP behind, so it's nice to know that templates are the way to go. Sincerely, Gour --=20 The work of a man who is unattached to the modes of material=20 nature and who is fully situated in transcendental knowledge=20 merges entirely into transcendence. http://atmarama.net | Hlapicina (Croatia) | GPG: 52B5C810
Mar 17 2012
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sat, Mar 17, 2012 at 09:45:51PM +0100, Gour wrote:
 On Sat, 17 Mar 2012 21:29:18 +0100
 Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:
 
 I had no idea what templates were when I started using D, and I
 thought I would never need to use them either. But now I use them
 extensively. They really become a natural tool in programming.
 They're so nice to use that I never have to reach for the big fat
 OOP monster, I can just write simple procedural code and use
 templates when I need some flexibility.
Thank you for this paragraph. ;) I also consider to write procedural/functional code in my project and leave OOP behind, so it's nice to know that templates are the way to go.
[...] I don't think you can discard OOP entirely. It still has its place IMO. When you need runtime polymorphism, OOP is still the best tool for the job. But yeah, quite often you don't need full-fledged runtime polymorphism, just a little compile-time flexibility (contrary to what the OO zealots would have you believe). D templates are more than suitable for the job. Using OO for this kind of thing just introduces unnecessary bloat and slow performance. (Not to mention, D templates can do some stuff that no OO can hope to attain. But it goes both ways. Templates can't do runtime polymorphism either.) T -- Sometimes the best solution to morale problems is just to fire all of the unhappy people. -- despair.com
Mar 17 2012
next sibling parent reply "Entity325" <lonewolf325 gmail.com> writes:
Wow, popular thread is popular.

Thanks for all the help, everyone.  I haven't read all of it, but 
I will take the time to sift through everything and see what I 
can apply.

Response to some of what I did read:
-I didn't conclude that templates are confusing because they 
confused me.  I concluded templates are confusing because both of 
the D language reference pages which talk about them have quotes 
at the top talking about how confusing Templates are.  Reflecting 
on my (short!) experience trying to learn them, I merely 
concluded that templates are confusing because nobody really 
makes an effort to explain them cleanly.  Now, the effort has 
been made about 22 times(by my count) in this thread alone, so 
that's a plus!

-While most of my programming professors had a decent idea of 
what they were doing, the classes themselves left massive, gaping 
holes in my education that I never even realized were there until 
I got a job writing Java code.  I don't even particularly LIKE 
Java.

Could just be that I'm a slow learner.

I messed around with Templates after making that post and learned 
that they seem to behave similar to Generic types in Java(I am 
forever finding warnings that a generic type hasn't been type 
specified in our code.  Sometimes I fix it, sometimes I leave it 
alone)  I tried rewriting my structs to utilize templates(I 
currently have separate versions for float and int types) but 
that did little more than illustrate just how lost I was, so I 
switched back.  It should be possible in theory, the question is 
the practice.

Study was further set back by the fact that I suddenly realized 
none of my operator overloads are working... at all.  It looks 
like it checks with the language reference page, but I think it's 
time to write another toy-sized learning program.
Mar 17 2012
parent "Nick Sabalausky" <a a.a> writes:
"Entity325" <lonewolf325 gmail.com> wrote in message 
news:vxadflowsujbbmpnrocg forum.dlang.org...
 -While most of my programming professors had a decent idea of what they 
 were doing, the classes themselves left massive, gaping holes in my 
 education that I never even realized were there until I got a job writing 
 Java code.  I don't even particularly LIKE Java.
IMHO, that means you're smart :) But you touched on an interesting thing about learning and knowledge: It's difficult to know how much is out there that you don't know. After all, if you're unaware of it, then how *can* you know that you're unaware of it? Arguably, one measure of personal progress is how much you suddenly realze there is that you *don't* know and didn't know. As amateurs, we're opened up to a new world and tend to feel like we know everything about the subject and can do anything with it. Then as we progress we learn how much there really is left to learn. Sort of Zen or Tao, really.
 I messed around with Templates after making that post and learned that 
 they seem to behave similar to Generic types in Java
Definitely. Generic types in language like Java can be thought of as one specific special case of templates. Templates are a good way to do generic types, but then they can *also* do a lot more than just types.
Mar 17 2012
prev sibling next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"H. S. Teoh" <hsteoh quickfur.ath.cx> wrote in message 
news:mailman.834.1332023905.4860.digitalmars-d puremagic.com...
 (Not to mention, D templates can do some stuff that no OO can hope to
 attain. But it goes both ways. Templates can't do runtime polymorphism
 either.)
Combined with compile-time reflection, I'm sure they could be used to create a runtime polymorphism tool, even multiple dispatch. Like I mentioned recently in a seperate thread, you'd just need to use templates/ctfe to automate/genericize this: void singleDispatch(Object o) { if(auto derived = cast(DerivedClassA)o) derived.foo(); else if(auto derived = cast(DerivedClassB)o) derived.foo(); else if(auto derived = cast(DerivedClassC)o) derived.foo(); //etc... } Although I guess *technically* you're still relying on OO polymorphism (in the form of downcasting) to achieve this. OTOH, you could still base it on Variant or Algebraic instead of (or in addition to) Object. Then you'd have built runtime polymorphism out of templates (among other things) without relying on OO.
Mar 17 2012
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sat, Mar 17, 2012 at 08:37:35PM -0400, Nick Sabalausky wrote:
 "H. S. Teoh" <hsteoh quickfur.ath.cx> wrote in message 
 news:mailman.834.1332023905.4860.digitalmars-d puremagic.com...
 (Not to mention, D templates can do some stuff that no OO can hope
 to attain. But it goes both ways. Templates can't do runtime
 polymorphism either.)
Combined with compile-time reflection, I'm sure they could be used to create a runtime polymorphism tool, even multiple dispatch. Like I mentioned recently in a seperate thread, you'd just need to use templates/ctfe to automate/genericize this: void singleDispatch(Object o) { if(auto derived = cast(DerivedClassA)o) derived.foo(); else if(auto derived = cast(DerivedClassB)o) derived.foo(); else if(auto derived = cast(DerivedClassC)o) derived.foo(); //etc... } Although I guess *technically* you're still relying on OO polymorphism (in the form of downcasting) to achieve this. OTOH, you could still base it on Variant or Algebraic instead of (or in addition to) Object. Then you'd have built runtime polymorphism out of templates (among other things) without relying on OO.
[...] But now you're just reimplementing OO in terms of templates. :-) You can do OO in C, too. (In fact, at work some of the C code I deal with are approximations to OO.) That has nothing to do with templates themselves per se. T -- He who does not appreciate the beauty of language is not worthy to bemoan its flaws.
Mar 17 2012
parent "Nick Sabalausky" <a a.a> writes:
"H. S. Teoh" <hsteoh quickfur.ath.cx> wrote in message 
news:mailman.839.1332031513.4860.digitalmars-d puremagic.com...
 On Sat, Mar 17, 2012 at 08:37:35PM -0400, Nick Sabalausky wrote:
 "H. S. Teoh" <hsteoh quickfur.ath.cx> wrote in message
 news:mailman.834.1332023905.4860.digitalmars-d puremagic.com...
 (Not to mention, D templates can do some stuff that no OO can hope
 to attain. But it goes both ways. Templates can't do runtime
 polymorphism either.)
Combined with compile-time reflection, I'm sure they could be used to create a runtime polymorphism tool, even multiple dispatch. Like I mentioned recently in a seperate thread, you'd just need to use templates/ctfe to automate/genericize this: void singleDispatch(Object o) { if(auto derived = cast(DerivedClassA)o) derived.foo(); else if(auto derived = cast(DerivedClassB)o) derived.foo(); else if(auto derived = cast(DerivedClassC)o) derived.foo(); //etc... } Although I guess *technically* you're still relying on OO polymorphism (in the form of downcasting) to achieve this. OTOH, you could still base it on Variant or Algebraic instead of (or in addition to) Object. Then you'd have built runtime polymorphism out of templates (among other things) without relying on OO.
[...] But now you're just reimplementing OO in terms of templates. :-) You can do OO in C, too. (In fact, at work some of the C code I deal with are approximations to OO.) That has nothing to do with templates themselves per se.
I'd argue: To view that (particularly if using Variants) as reimplementing OO, is to blur the distinction between OO and polymorphism. OO is such a popular form of polymorphism that we're conditioned to look at polymorphism and say "Oh, that's OO". Really, OO is just one way of doing polymorphism. You define a class. You define a subclass and override its methods. Etc. Other forms of polymorphism exist, such as defining over*loads* and dispatching to them based on the type in a Variant - which, AIUI, is what some non-OO polymorphic languages do behind-the-scenes (though I could be wrong). Uhh, i *think* ML is one such example. Anyway, these other types of polymorphism can easily look like OO because, since they're all just forms of polymorphism, they look like they're just variations on the same fundamental thing. And that's because they are just variations on the same fundamental thing: polymorphism.
Mar 17 2012
prev sibling parent reply Gour <gour atmarama.net> writes:
On Sat, 17 Mar 2012 15:39:53 -0700
"H. S. Teoh" <hsteoh quickfur.ath.cx> wrote:

 I don't think you can discard OOP entirely. It still has its place
 IMO. When you need runtime polymorphism, OOP is still the best tool
 for the job.
Hmm, if we want to write more FP-like type-safe code, I wonder how much we'd need runtime polymorphism at all? Sincerely, Gour --=20 Never was there a time when I did not exist,=20 nor you, nor all these kings; nor in the future=20 shall any of us cease to be. http://atmarama.net | Hlapicina (Croatia) | GPG: 52B5C810
Mar 17 2012
parent reply Paulo Pinto <pjmlp progtools.org> writes:
Am 18.03.2012 07:41, schrieb Gour:
 On Sat, 17 Mar 2012 15:39:53 -0700
 "H. S. Teoh"<hsteoh quickfur.ath.cx>  wrote:

 I don't think you can discard OOP entirely. It still has its place
 IMO. When you need runtime polymorphism, OOP is still the best tool
 for the job.
Hmm, if we want to write more FP-like type-safe code, I wonder how much we'd need runtime polymorphism at all? Sincerely, Gour
Enterprise software?
Mar 18 2012
parent Gour <gour atmarama.net> writes:
On Sun, 18 Mar 2012 11:04:45 +0100
Paulo Pinto <pjmlp progtools.org> wrote:

 Enterprise software?
Not here, we'll write open-source project. ;) Sincerely, Gour --=20 All living bodies subsist on food grains, which are produced=20 from rains. Rains are produced by performance of yaj=C3=B1a [sacrifice],=20 and yaj=C3=B1a is born of prescribed duties. http://atmarama.net | Hlapicina (Croatia) | GPG: 52B5C810
Mar 19 2012
prev sibling next sibling parent reply FeepingCreature <default_357-line yahoo.de> writes:
A template is a parameterized namespace. That is, it is a namespace (a name
through which other objects can be accessed) that may be passed parameters that
can modify the nature of the stuff inside.

If a template is a compile-time function, then the equivalent of a function
call - the association of a template description with
specific arguments - is called a template instantiation.

Templates have the following properties:

* they're unique; that is, a member of a template instantiation always refers
the same as a member of the same instantiation in a different module

* they're compiletime; that is, it is impossible to instantiate a template
while the program runs.

* In D, if a template contains only one member, and its name is the same as the
template, then the member is assumed to *be* the template instantiation.

That's all!

In D, void foo(T)(T t) { } is just short for template foo(T) { void foo(T t) {
} }.

So foo!(int) == "member foo of instantiation of template foo with parameter T =
int".

There's a shortcut for this, called IFTI, "implicit function template
instantiation". If you have a function template - that is,
a template containing only one function with the same name as the template -
then calling the template as if it was a function will
simply instantiate it with the type of the arguments.

Example:

template bar(T...){ void bar(T t) { writefln(t); } }

bar(2, 3, 4); // is equivalent to
bar!(int, int, int)(2, 3, 4); // is equivalent to
bar!(int, int, int).bar(2, 3, 4);
Mar 17 2012
parent reply Derek <ddparnell bigpond.com> writes:
On Sun, 18 Mar 2012 17:01:00 +1100, FeepingCreature  
<default_357-line yahoo.de> wrote:

 There's a shortcut for this, called IFTI, "implicit function template  
 instantiation" ...
What would be useful is ... template bar(T...){ void bar(T t) { writefln(t); } } int a,b,c; bar!(a, b, c); // is equivalent to bar!(int, int, int).bar(a, b, c); -- Derek Parnell Melbourne, Australia
Mar 18 2012
parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 3/18/12, Derek <ddparnell bigpond.com> wrote:
 What would be useful is ...
   bar!(a, b, c); // is equivalent to
   bar!(int, int, int).bar(a, b, c);
You mean like this? template bar(T...) { void bar() { writeln(T); } } void main() { int a = 1, b = 2, c = 3; bar!(a, b, c); }
Mar 18 2012
next sibling parent "Nick Sabalausky" <a a.a> writes:
"Andrej Mitrovic" <andrej.mitrovich gmail.com> wrote in message 
news:mailman.851.1332059038.4860.digitalmars-d puremagic.com...
 On 3/18/12, Derek <ddparnell bigpond.com> wrote:
 What would be useful is ...
   bar!(a, b, c); // is equivalent to
   bar!(int, int, int).bar(a, b, c);
You mean like this? template bar(T...) { void bar() { writeln(T); } } void main() { int a = 1, b = 2, c = 3; bar!(a, b, c); }
Shouldn't that be: template bar(T...) { void bar(T args) { writeln(args); } } void main() { int a = 1, b = 2, c = 3; bar(a, b, c); } Or did I misunderstand the point?
Mar 18 2012
prev sibling parent reply Derek <ddparnell bigpond.com> writes:
On Sun, 18 Mar 2012 19:16:02 +1100, Andrej Mitrovic  
<andrej.mitrovich gmail.com> wrote:

 On 3/18/12, Derek <ddparnell bigpond.com> wrote:
 What would be useful is ...
   bar!(a, b, c); // is equivalent to
   bar!(int, int, int).bar(a, b, c);
You mean like this? template bar(T...) { void bar() { writeln(T); } } void main() { int a = 1, b = 2, c = 3; bar!(a, b, c); }
Almost, but more like this ... template add(X,Y,Z) { X add(Y a, Z b) { return cast(X) (cast(X)a + cast(X)b); } } void main() { double s; int t; ulong u; s = 1.23; t = 123; u = 456; t = add!(u,s); writefln( "%s %s %s", s,t, u ); } This currently errors with ... "Error: template instance add!(u,s) add!(u,s) does not match template declaration add(X,Y,Z)" -- Derek Parnell Melbourne, Australia
Mar 18 2012
parent reply FeepingCreature <default_357-line yahoo.de> writes:
On 03/18/12 11:29, Derek wrote:
 On Sun, 18 Mar 2012 19:16:02 +1100, Andrej Mitrovic
<andrej.mitrovich gmail.com> wrote:
 
 On 3/18/12, Derek <ddparnell bigpond.com> wrote:
 What would be useful is ...
   bar!(a, b, c); // is equivalent to
   bar!(int, int, int).bar(a, b, c);
You mean like this? template bar(T...) { void bar() { writeln(T); } } void main() { int a = 1, b = 2, c = 3; bar!(a, b, c); }
Almost, but more like this ... template add(X,Y,Z) { X add(Y a, Z b) { return cast(X) (cast(X)a + cast(X)b); } } void main() { double s; int t; ulong u; s = 1.23; t = 123; u = 456; t = add!(u,s); writefln( "%s %s %s", s,t, u ); } This currently errors with ... "Error: template instance add!(u,s) add!(u,s) does not match template declaration add(X,Y,Z)"
why would you do that what do you want to _do_ it sounds like you're frantically trying to nail templates into a shape that they really really really aren't meant for in any case what is wrong with auto add(T)(T t) { return t[0] + t[1]; }
Mar 18 2012
next sibling parent reply FeepingCreature <default_357-line yahoo.de> writes:
On 03/18/12 11:36, FeepingCreature wrote:
 On 03/18/12 11:29, Derek wrote:
 On Sun, 18 Mar 2012 19:16:02 +1100, Andrej Mitrovic
<andrej.mitrovich gmail.com> wrote:

 On 3/18/12, Derek <ddparnell bigpond.com> wrote:
 What would be useful is ...
   bar!(a, b, c); // is equivalent to
   bar!(int, int, int).bar(a, b, c);
You mean like this? template bar(T...) { void bar() { writeln(T); } } void main() { int a = 1, b = 2, c = 3; bar!(a, b, c); }
Almost, but more like this ... template add(X,Y,Z) { X add(Y a, Z b) { return cast(X) (cast(X)a + cast(X)b); } } void main() { double s; int t; ulong u; s = 1.23; t = 123; u = 456; t = add!(u,s); writefln( "%s %s %s", s,t, u ); } This currently errors with ... "Error: template instance add!(u,s) add!(u,s) does not match template declaration add(X,Y,Z)"
why would you do that what do you want to _do_ it sounds like you're frantically trying to nail templates into a shape that they really really really aren't meant for in any case what is wrong with auto add(T)(T t) { return t[0] + t[1]; }
oh you may have misunderstood me a template is a **compile time parameterized namespace** its parameters are **types** and **constants**, not runtime values "add" is a "namespace that is instantiated with the types float and" OOOOOOOOOOOOOOOOOOOOH I get what you want. :D template add(T) { template add(U...) { auto add(U u) { T res; foreach (value; u) res += value; return res; } } } void main() { double s; int t; ulong u; s = 1.23; t = 123; u = 456; t = add!int(u, s); writefln( "%s %s %s", s, t, u ); }
Mar 18 2012
parent reply FeepingCreature <default_357-line yahoo.de> writes:
On 03/18/12 11:39, FeepingCreature wrote:
 On 03/18/12 11:36, FeepingCreature wrote:
 On 03/18/12 11:29, Derek wrote:
 On Sun, 18 Mar 2012 19:16:02 +1100, Andrej Mitrovic
<andrej.mitrovich gmail.com> wrote:

 On 3/18/12, Derek <ddparnell bigpond.com> wrote:
 What would be useful is ...
   bar!(a, b, c); // is equivalent to
   bar!(int, int, int).bar(a, b, c);
You mean like this? template bar(T...) { void bar() { writeln(T); } } void main() { int a = 1, b = 2, c = 3; bar!(a, b, c); }
Almost, but more like this ... template add(X,Y,Z) { X add(Y a, Z b) { return cast(X) (cast(X)a + cast(X)b); } } void main() { double s; int t; ulong u; s = 1.23; t = 123; u = 456; t = add!(u,s); writefln( "%s %s %s", s,t, u ); } This currently errors with ... "Error: template instance add!(u,s) add!(u,s) does not match template declaration add(X,Y,Z)"
why would you do that what do you want to _do_ it sounds like you're frantically trying to nail templates into a shape that they really really really aren't meant for in any case what is wrong with auto add(T)(T t) { return t[0] + t[1]; }
oh you may have misunderstood me a template is a **compile time parameterized namespace** its parameters are **types** and **constants**, not runtime values "add" is a "namespace that is instantiated with the types float and" OOOOOOOOOOOOOOOOOOOOH I get what you want. :D template add(T) { template add(U...) { auto add(U u) { T res; foreach (value; u) res += value; return res; } } } void main() { double s; int t; ulong u; s = 1.23; t = 123; u = 456; t = add!int(u, s); writefln( "%s %s %s", s, t, u ); }
which of course doesn't work because you can't add a double to an int. So .. maybe I don't get what you want.
Mar 18 2012
parent reply Derek <ddparnell bigpond.com> writes:
On Sun, 18 Mar 2012 21:40:10 +1100, FeepingCreature  
<default_357-line yahoo.de> wrote:

 On 03/18/12 11:39, FeepingCreature wrote:
 On 03/18/12 11:36, FeepingCreature wrote:
 On 03/18/12 11:29, Derek wrote:
 On Sun, 18 Mar 2012 19:16:02 +1100, Andrej Mitrovic  
 <andrej.mitrovich gmail.com> wrote:

 On 3/18/12, Derek <ddparnell bigpond.com> wrote:
 What would be useful is ...
   bar!(a, b, c); // is equivalent to
   bar!(int, int, int).bar(a, b, c);
You mean like this? template bar(T...) { void bar() { writeln(T); } } void main() { int a = 1, b = 2, c = 3; bar!(a, b, c); }
Almost, but more like this ... template add(X,Y,Z) { X add(Y a, Z b) { return cast(X) (cast(X)a + cast(X)b); } } void main() { double s; int t; ulong u; s = 1.23; t = 123; u = 456; t = add!(u,s); writefln( "%s %s %s", s,t, u ); } This currently errors with ... "Error: template instance add!(u,s) add!(u,s) does not match template declaration add(X,Y,Z)"
why would you do that what do you want to _do_ it sounds like you're frantically trying to nail templates into a shape that they really really really aren't meant for in any case what is wrong with auto add(T)(T t) { return t[0] + t[1]; }
oh you may have misunderstood me a template is a **compile time parameterized namespace** its parameters are **types** and **constants**, not runtime values "add" is a "namespace that is instantiated with the types float and" OOOOOOOOOOOOOOOOOOOOH I get what you want. :D template add(T) { template add(U...) { auto add(U u) { T res; foreach (value; u) res += value; return res; } } } void main() { double s; int t; ulong u; s = 1.23; t = 123; u = 456; t = add!int(u, s); writefln( "%s %s %s", s, t, u ); }
which of course doesn't work because you can't add a double to an int. So .. maybe I don't get what you want.
The 'adding' is not the point; it could be any functionality. The point I was trying to get across was that it would be useful if the compiler could infer the type parameters of a template instantiation from the types of the data items used in the instantiation reference. My original code would work if I had of written ... t = add!(int, ulong, double)(u, s); but I was thinking that coding "(int, ulong, double)" is a bit redundant as this information is available to the compiler already as the arguments' types. And by the way, none of the counter examples so far would compile for me. Still complaining about "add!(u,s) does not match template declaration ..." -- Derek Parnell Melbourne, Australia
Mar 18 2012
parent reply Derek <ddparnell bigpond.com> writes:
On Sun, 18 Mar 2012 22:00:06 +1100, Derek <ddparnell bigpond.com> wrote:

 The 'adding' is not the point; it could be any functionality. The point  
 I was trying to get across was that it would be useful if the compiler  
 could infer the type parameters of a template instantiation from the  
 types of the data items used in the instantiation reference.
The best I can come up with so far is ... import std.stdio; template add(X, Y,Z) { auto add(X c, Y a, Z b) { return cast(X)a + cast(X)b; } } void main() { double s; int t; ulong u; s = 1.23; t = 123; u = 456; writeln(add(t,u,s)); // --> 467 writeln(add(s,t,s)); // --> 124.23 } It seems that the templated function's return type is not used when searching for matching templates, so I have to explicitly include something in the function's signature just to use it as the returned data's type. -- Derek Parnell Melbourne, Australia
Mar 18 2012
next sibling parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 18.03.2012 15:34, Derek wrote:
 On Sun, 18 Mar 2012 22:00:06 +1100, Derek <ddparnell bigpond.com> wrote:

 The 'adding' is not the point; it could be any functionality. The
 point I was trying to get across was that it would be useful if the
 compiler could infer the type parameters of a template instantiation
 from the types of the data items used in the instantiation reference.
The best I can come up with so far is ...
[snip] Why not this: template add(X) { auto add(Y,Z)(Y a, Z b) { return cast(X)a + cast(X)b; } } void main() { double s; int t; ulong u; s = 1.23; t = 123; u = 456; writeln(add!int(u,s)); // --> 467 writeln(add!double(t,s)); // --> 124.23 } In short: use type parameters when you parametrize on types. Use IFTI to avoid typing parameters that could be inferred. X type you cast to, clearly can't be inferred from arguments.
 It seems that the templated function's return type is not used when
 searching for matching templates, so I have to explicitly include
 something in the function's signature just to use it as the returned
 data's type.
No just provide type, dummy values smack of flawed dispatch techniques from C++ STL. -- Dmitry Olshansky
Mar 18 2012
prev sibling parent Artur Skawina <art.08.09 gmail.com> writes:
On 03/18/12 12:34, Derek wrote:
 On Sun, 18 Mar 2012 22:00:06 +1100, Derek <ddparnell bigpond.com> wrote:
 
 The 'adding' is not the point; it could be any functionality. The point I was
trying to get across was that it would be useful if the compiler could infer
the type parameters of a template instantiation from the types of the data
items used in the instantiation reference.
The best I can come up with so far is ... import std.stdio; template add(X, Y,Z) { auto add(X c, Y a, Z b) { return cast(X)a + cast(X)b; } } void main() { double s; int t; ulong u; s = 1.23; t = 123; u = 456; writeln(add(t,u,s)); // --> 467 writeln(add(s,t,s)); // --> 124.23 } It seems that the templated function's return type is not used when searching for matching templates, so I have to explicitly include something in the function's signature just to use it as the returned data's type.
You can either let the compiler figure out the right common type or give it explicitly: auto add(X=void,Y,Z)(Y a, Z b) { static if (is(X==void)) alias typeof(a+b) RX; else alias X RX; return cast(RX)a + cast(RX)b; } Both "add(u,s)" and "add!int(u,s)" will work; note that the first version returns a 'double', but that's probably what you want, when not explicitly asking for an 'int'. artur
Mar 19 2012
prev sibling parent reply Derek <ddparnell bigpond.com> writes:
On Sun, 18 Mar 2012 21:36:46 +1100, FeepingCreature  
<default_357-line yahoo.de> wrote:


 why would you do that
To make coding easier to write AND read.
 what do you want to _do_
Infer template arguments from the data types presented in the data values supplied on the instantiation statement.
 it sounds like you're frantically trying to nail templates into a shape  
 that they really really really aren't meant for
I assumed D templates were a type of template; a model for real runnable code that the compiler can instantiate based on the arguments supplied.
 in any case what is wrong with auto add(T)(T t) { return t[0] + t[1]; }
It doesn't work. -- Derek Parnell Melbourne, Australia
Mar 18 2012
parent FeepingCreature <default_357-line yahoo.de> writes:
On 03/18/12 12:05, Derek wrote:
 On Sun, 18 Mar 2012 21:36:46 +1100, FeepingCreature
<default_357-line yahoo.de> wrote:
 
 
 why would you do that
To make coding easier to write AND read.
 what do you want to _do_
Infer template arguments from the data types presented in the data values supplied on the instantiation statement.
 it sounds like you're frantically trying to nail templates into a shape that
they really really really aren't meant for
I assumed D templates were a type of template; a model for real runnable code that the compiler can instantiate based on the arguments supplied.
Yes but you keep trying to pass runtime arguments to a compiletime construct. I think you understand what templates are but not how to use them.
 
 in any case what is wrong with auto add(T)(T t) { return t[0] + t[1]; }
It doesn't work.
Okay, let's try this. template add(T) { template add(U...) { T add(U u) { T res; foreach (entry; u) res += cast(T) entry; return res; } } } add!int(2, 3, 4.0, 5.0f);
Mar 18 2012
prev sibling parent reply Sean Kelly <sean invisibleduck.org> writes:
On Mar 17, 2012, at 10:14 AM, Entity325 wrote:

 (Sorry if this is the wrong place for this, or if there's already a =
thread in existence which would be better. If either of these is the = case, simply point me in the right direction, and I'll be on my way.)
=20
 My first interaction with Templates was about 5 years ago, in a C++ =
class at my university. I immediately thought "A general type? This = would be great for my logger!" and tried to implement them into the = small library I had been developing to save time on the class = assignments.
=20
 Naturally, I didn't understand them, so after a couple of half-hearted =
attempts, I gave up and went back to doing things the way I had before. = I've avoided Templates since then, because they don't make any sense! I see this a lot, and it's why I wrote the chapter on templates for = Learn to Tango with D. I don't think I can sort out releasing the = chapter though. One approach is to think of templates as compile-time = polymorphism. In Java, you might create a linked-list as: class List { void insert(Object e) { head =3D new Node(e, head); } static class Node { Object elem; Node next; this(Object e, Node n) { elem =3D e;=20 next =3D n; } } } This works fine so long as everything you store in the list derives from = Object, and you have to remember what the list holds so when you examine = an element you cast it to Integer or whatever. But both of these are = problems. First, you can't store concrete types (int, float, etc) in = the list, and second, the compiler can't help you make sure you only = store instances of Integer or whatever in the list (for the record, Java = does have auto-boxing and generics now to deal with these issues). In = D, we can address these problems by converting List to a template class. Templates are really just a means of telling the compiler to generate = code according to some simple rules. So looking at the List class = above, if we want it to hold anything instead of just Objects, we = replace instances of "Object" above with a type signifier. The long = form is easiest to understand: template (T) { class List { void insert(T e) { head =3D new Node(e, head); } static class Node { T elem; Node next; =20 this(T e, Node n) { elem =3D e; next =3D n; } } } } Notice that all we did to create this template was replace "Object" with = an arbitrarily chosen name "T", then enclose the whole thing in a = "template" block with one parameter, T. This tells the compiler that = what's contained is a template with a variable type T. Let's say you = declare one instance of this container: auto list =3D new List!(int); The compiler sees "int" as the parameter for template argument "T" and = generates code for the list above with "int" written wherever "T" is, = so: class List { void insert(int e) { head =3D new Node(e, head); } static class Node { int elem; Node next; =20 this(int e, Node n) { elem =3D e; next =3D n; } } } This is done early enough during compilation that it's as if you wrote = the code by hand, so you'll get a compile error if you try to insert = something that isn't an int, etc. The declaration of template types that introduce their own scope (ie. = structs and classes) can eliminate the enclosing "template" scope and = move the template list down to after the type name, so the original = template declaration above is equivalent to: class List (T) { ... } Template functions work exactly the same way, except that the compiler = can infer the types of template parameters based on the function = argument list, so: template (T) { T add(T a, T b) { return a + b; } which can be written in a more compact form as: T add(T)(T a, T b) { return a + b; } Note how the template list moved after the function name, just like with = the List class above. Now, you can call this as: auto result =3D add!(int)(1, 2); assert(result =3D=3D 3); Or let the compiler determine T for you. The arguments above are both = of type int, so if you write: auto result =3D add(1, 2); assert(result =3D=3D 3); The compiler sees that the arguments for add() are type int and does the = replacement automatically. Now fast-forward from the original conception of templates to today. D = also allows you to pass data as template arguments, so this also works: template (int x) { int add(int y) { return x + y; } } or again: int add(int x)(int y) { return x + y; } And calling: int val =3D 7; auto result =3D add!(5)(val); Generates the function: int add!(5)(int y) { return 5 + y; } The more advanced template stuff is just riffs on these ideas. It all = works by having the compiler generate code, replacing type and variable = symbols in the template list with whatever was specified when the = template was called. And back to the original motivation above, this = gives you the performance and safety of hand-written code with the ease = of maintenance of polymorphic code, since you only have to maintain a = single copy. I dunno if any of that helped, but if not, maybe some more directed = questions in D.learn? The basic idea behind templates is very = straightforward. The biggest problem seems to be that most people talk = about them like they're some sort of black magic, so finding a = straightforward explanation can be surprisingly hard.=
Mar 19 2012
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 3/19/12 1:59 PM, Sean Kelly wrote:
 I see this a lot, and it's why I wrote the chapter on templates for
 Learn to Tango with D.  I don't think I can sort out releasing the
 chapter though.  One approach is to think of templates as
 compile-time polymorphism.  In Java, you might create a linked-list
 as:
[snip] There have been a couple of long good answers in this thread, and it would be a shame to let them scroll by the way newsgroup messages do. I suggest authors to repackage their posts as blog entries or articles. Andrei
Mar 19 2012
next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Mar 19, 2012 at 02:27:04PM -0500, Andrei Alexandrescu wrote:
 On 3/19/12 1:59 PM, Sean Kelly wrote:
I see this a lot, and it's why I wrote the chapter on templates for
Learn to Tango with D.  I don't think I can sort out releasing the
chapter though.  One approach is to think of templates as
compile-time polymorphism.  In Java, you might create a linked-list
as:
[snip] There have been a couple of long good answers in this thread, and it would be a shame to let them scroll by the way newsgroup messages do. I suggest authors to repackage their posts as blog entries or articles.
[...] It would be nice if somebody could write up a general introduction to the idea of templates (not specific to D), the motivations behind it, perhaps some historical background, and then eventually lead up to advanced template tricks using D as the prime example. Then not only we can point newbies at the document, but it can also serve as D propaganda. I'd take a stab at this, except that my free time is limited and most of it is currently being used for refining my AA implementation so that it can (hopefully) replace the current AA mess. T -- "Hi." "'Lo."
Mar 19 2012
prev sibling next sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Mon, Mar 19, 2012 at 20:37, H. S. Teoh <hsteoh quickfur.ath.cx> wrote:
 It would be nice if somebody could write up a general introduction to
 the idea of templates (not specific to D), the motivations behind it,
 perhaps some historical background, and then eventually lead up to
 advanced template tricks using D as the prime example.

 Then not only we can point newbies at the document, but it can also
 serve as D propaganda.

 I'd take a stab at this, except that my free time is limited and most of
 it is currently being used for refining my AA implementation so that it
 can (hopefully) replace the current AA mess.
As Ali said, there is a chapter of his D book about templates: http://ddili.org/ders/d.en/templates.html And I wrote a document on templates (I call it a tutorial): https://github.com/PhilippeSigaud/D-templates-tutorial/blob/master/dtemplates.pdf I saw someone said it skips too fast to over the easy stuff. Should I say more on the first chapters?
Mar 19 2012
prev sibling parent "Nick Sabalausky" <a a.a> writes:
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
news:jk81a6$2o7l$1 digitalmars.com...
 On 3/19/12 1:59 PM, Sean Kelly wrote:
 I see this a lot, and it's why I wrote the chapter on templates for
 Learn to Tango with D.  I don't think I can sort out releasing the
 chapter though.  One approach is to think of templates as
 compile-time polymorphism.  In Java, you might create a linked-list
 as:
[snip] There have been a couple of long good answers in this thread, and it would be a shame to let them scroll by the way newsgroup messages do. I suggest authors to repackage their posts as blog entries or articles.
I've been planning to do so with mine, just haven't gotten to it yet...
Mar 19 2012