August 11, 2003 Re: D User Poll | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Yokomiso | "Daniel Yokomiso" <daniel_yokomiso@yahoo.com.br> wrote in message news:be9gje$19cp$1@digitaldaemon.com... > More powerful template syntax ;) Any specific ideas? |
August 11, 2003 Re: D User Poll | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | In article <bh92nq$2403$1@digitaldaemon.com>, Walter says... >"Daniel Yokomiso" <daniel_yokomiso@yahoo.com.br> wrote in message news:be9gje$19cp$1@digitaldaemon.com... >> More powerful template syntax ;) >Any specific ideas? I'd really like to be able to treat an instance as a type: alias instance List<Foo> FooList; FooList.List myFooList; FooList.Iterator i; Also, it seems like the approach to implementing default template parameters is: template List(T, SomeOtherType) { class List { .. } } template List(T) { alias List instance List(T, DefaultOtherType) List; } But what if the first template defined a dozen classes? Do they all need to be aliased in the single argument template? Being able to pass a template instance as a template parameter would be fly as well: template Comparator(T) { int compare(T i, T j) { return i.compare(j); } } template List(T, Cmp) { class List { void insertSorted(T a) { for (T p = head ; p && Cmp.compare(p, t) <= 0 ; p = p.next) you_get_the_idea(p); } } } instance List(Foo, instance Comparator(Foo)) fooList; // doesn't work |
August 12, 2003 Re: D User Poll | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris Sokol | I think I can work with that. -Walter "Chris Sokol" <chris@echosproject.org> wrote in message news:bh97gp$29e3$1@digitaldaemon.com... > In article <bh92nq$2403$1@digitaldaemon.com>, Walter says... > >"Daniel Yokomiso" <daniel_yokomiso@yahoo.com.br> wrote in message news:be9gje$19cp$1@digitaldaemon.com... > >> More powerful template syntax ;) > >Any specific ideas? > > I'd really like to be able to treat an instance as a type: > > alias instance List<Foo> FooList; > > FooList.List myFooList; > FooList.Iterator i; > > Also, it seems like the approach to implementing default template parameters is: > > template List(T, SomeOtherType) { > class List { > .. > } > } > > template List(T) { > alias List instance List(T, DefaultOtherType) List; > } > > But what if the first template defined a dozen classes? Do they all need to be > aliased in the single argument template? > > Being able to pass a template instance as a template parameter would be fly as > well: > > template Comparator(T) { > int compare(T i, T j) { > return i.compare(j); > } > } > > template List(T, Cmp) { > class List { > void insertSorted(T a) { > for (T p = head ; p && Cmp.compare(p, t) <= 0 ; p = p.next) > you_get_the_idea(p); > } > } > } > > instance List(Foo, instance Comparator(Foo)) fooList; // doesn't work > > |
August 13, 2003 Re: D User Poll | ||||
---|---|---|---|---|
| ||||
Posted in reply to Burton Radons | "Burton Radons" <loth@users.sourceforge.net> wrote in message news:bgemr5$19q5$1@digitaldaemon.com... > C++ template libraries are the most illegible things I've ever had the misfortune of dealing with. D template libraries will be worse (at least, when they finally come around) because of even more syntactual baggage; so much so that it lessens the variety of applications they can be pragmatically used with. Just take C++ templates, make them take much more typing but be less capable in important ways, and you have D templates. While D templates do require more typing in the (trivial) example you provided, if the templates have a mix of function and class templates grouped together, the D template method is far less typing. It's also possible to use the aliases to reduce the typing: alias instance Min(int).min mymin; int c = mymin(a,b); The syntax you proposed is certainly intriguing, and works well for things like min. I'm less sure it will work well for things like partial specialization, etc. |
August 13, 2003 Re: D User Poll | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean L. Palmer | "Sean L. Palmer" <palmer.sean@verizon.net> wrote in message news:bgm2vi$23gg$1@digitaldaemon.com... > Yes, generics don't have to be a hideous boil on the face of the language. ;) LOL! |
August 23, 2003 Re: D User Poll | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | "Walter" <walter@digitalmars.com> escreveu na mensagem news:bh92nq$2403$1@digitaldaemon.com... > > "Daniel Yokomiso" <daniel_yokomiso@yahoo.com.br> wrote in message news:be9gje$19cp$1@digitaldaemon.com... > > More powerful template syntax ;) > > Any specific ideas? Hi, Here we go again ;) There are a few things that are impossible to do currently: template TMatrix(T, int ROWS, int COLUMNS) { class Matrix { private T[] data = new T[ROWS * COLUWNS]; public Matrix add(Matrix other) { // code goes here } public Matrix mul(Matrix other) { // code goes here } } } The mul operation can be specified. Our template defines the matrix component's type (T) and its dimensions (M, N). It's ok for add, but mul must use different values for M and N, something in the lines of: template TMatrix(T, int ROWS, int COLUMNS) { class Matrix { private T[] data = new T[ROWS * COLUWNS]; public Matrix add(Matrix other) { // code goes here } public instance TMatrix(T, COLUMNS, N).Matrix mul(instance TMatrix(T, COLUMNS, N).Matrix other) { // code goes here } } } In this way (I'm not arguing about the syntax, just the semantics) we can say to the compiler: "a matrix can multiply only matrix with a row size equal to its column size.". Perhaps a better syntax would be: template TMatrix(T, int ROWS, int COLUMNS) { class Matrix { private T[] data = new T[ROWS * COLUWNS]; public Matrix add(Matrix other) { // code goes here } template implicit (N) { /* "implicit" is a keyword to make a template with implicit instantiation. * we could also use the "this" keyword or whatever, as long as the programmer * doesn't need to write something like "A instance A.TMul(B.columns()).mul(B)" to * safely multiply the A and B matrices. */ alias instance TMatrix(T, COLUMNS, N).Matrix OtherMatrix; alias instance TMatrix(T, ROWS, N).Matrix ResultMatrix; public ResultMatrix mul(OtherMatrix other) { // code goes here } } } } In this case we have some kind of implicit instantiation, but this kind of template mechanism will be available in the next versions of Java and C#. Also almost all statically-typed functional programming languages have this kind of type system. The parameters for the "implicit" template should be always statically determined from the operation's parameters, in this case the "other" Matrix template instance. My other example involving statically-typed units would become: template TUnit(T, int C, int G, int S) { struct Unit { private T value; public Unit add(Unit other) { // code goes here } template implicit (C1, G1, S1) { alias instance TUnit(T, C1, G1, S1).Unit OtherUnit; alias instance TUnit(T, C + C1, G + G1, S + S1).Unit ResultUnit; public ResultUnit mul(OtherUnit other) { // code goes here } } // other methods here } } template TUnits(T) { alias instance TUnit(T, 1, 0, 0).Unit Length; alias instance TUnit(T, 0, 1, 0).Unit Mass; alias instance TUnit(T, 0, 0, 1).Unit Time; alias instance TUnit(T, 1, 0, -1).Unit Speed; alias instance TUnit(T, 1, 0, -2).Unit Acceleration; const Length meter = {100}; const Time second = {1}; } // all operations below should be statically verified instance TUnits(double).Acceleration a = 2 * meter / (second * second); instance TUnits(double).Length l = 10 * meter; instance TUnits(double).Speed s = a * l; This kind of expressiveness will make D very suitable to reliable, safe, efficient numeric computing. We could define algorithms in terms of precision (template parameters) and be able to instantiate different versions of the algorithm for different precisions, or compute the result precision from the parameters and the algorithm used (as in dr. Kahan's paper). Other issue is how to deal with multiple template versions and code sharing: template TList(T) { class List { public void sort(int delegate(T, T) comparator) { // code goes here } } } template TList(T : Comparable) { /* how can we instantiate the previous definition to create the "Super" alias? */ private alias instance TList(T).List Super; class List : Super { public void sort() { // code goes here } } } With the class definition we can "cheat" and create subclasses of the earlier definitions, but with plain templates it fails: template TAssert(T) { public void equals(T expected, T received) { // code goes here } } template TAssert(T : double) { public void equals(T expected, T received, double precision) { // code goes here } } instance TAssert(double) check; check.equals(1.001, 1.000, 0.001); // works as expected check.equals(1.0, 1.0); // fails The second "TAssert" definition is an extension/specialization of the previous template, it should have all definitions from the earlier template definition, plus the new ones, overriding accordingly. Some kind of template inheritance is necessary, either explicit or implicit. Otherwise we'll have to duplicate the definitions for all specializations. I think that these two extensions are important and necessary to both library writers and user programmers. Also the unification of the type system, regarding delegates and function pointers, allowing templates with function parameters. Best regards, Daniel Yokomiso. "Time is the best teacher unfortunately it kills all its students." --- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.510 / Virus Database: 307 - Release Date: 14/8/2003 |
August 23, 2003 Re: D User Poll | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Yokomiso | "Daniel Yokomiso" <daniel_yokomiso@yahoo.com.br> wrote in message news:bi6iu9$2u47$1@digitaldaemon.com... > template TMatrix(T, int ROWS, int COLUMNS) { > class Matrix { > private T[] data = new T[ROWS * COLUWNS]; > public Matrix add(Matrix other) { > // code goes here > } > public Matrix mul(Matrix other) { > // code goes here > } > } > } > > > The mul operation can be specified. Our template defines the matrix > component's type (T) and its dimensions (M, N). It's ok for add, but mul > must use different values for M and N, something in the lines of: > > template TMatrix(T, int ROWS, int COLUMNS) { > class Matrix { > private T[] data = new T[ROWS * COLUWNS]; > public Matrix add(Matrix other) { > // code goes here > } > public instance TMatrix(T, COLUMNS, N).Matrix mul(instance > TMatrix(T, COLUMNS, N).Matrix other) { > // code goes here > } > } > } > > In this way (I'm not arguing about the syntax, just the semantics) we > can say to the compiler: "a matrix can multiply only matrix with a row size > equal to its column size.". Perhaps a better syntax would be: > > template TMatrix(T, int ROWS, int COLUMNS) { > class Matrix { > private T[] data = new T[ROWS * COLUWNS]; > public Matrix add(Matrix other) { > // code goes here > } > template implicit (N) { > /* "implicit" is a keyword to make a template with implicit instantiation. > * we could also use the "this" keyword or whatever, as long as the > programmer > * doesn't need to write something like "A instance > A.TMul(B.columns()).mul(B)" to > * safely multiply the A and B matrices. > */ > alias instance TMatrix(T, COLUMNS, N).Matrix OtherMatrix; > alias instance TMatrix(T, ROWS, N).Matrix ResultMatrix; > public ResultMatrix mul(OtherMatrix other) { > // code goes here > } > } > } > } > > In this case we have some kind of implicit instantiation, but this kind > of template mechanism will be available in the next versions of Java and C#. > Also almost all statically-typed functional programming languages have this > kind of type system. > The parameters for the "implicit" template should be always statically > determined from the operation's parameters, in this case the "other" Matrix > template instance. I don't get it. Is the implicit template a new template within TMatrix? Where does N come from again? > My other example involving statically-typed units would become: > > template TUnit(T, int C, int G, int S) { > struct Unit { > private T value; > public Unit add(Unit other) { > // code goes here > } > template implicit (C1, G1, S1) { > alias instance TUnit(T, C1, G1, S1).Unit OtherUnit; > alias instance TUnit(T, C + C1, G + G1, S + S1).Unit ResultUnit; > public ResultUnit mul(OtherUnit other) { > // code goes here > } > } > // other methods here > } > } > template TUnits(T) { > alias instance TUnit(T, 1, 0, 0).Unit Length; > alias instance TUnit(T, 0, 1, 0).Unit Mass; > alias instance TUnit(T, 0, 0, 1).Unit Time; > alias instance TUnit(T, 1, 0, -1).Unit Speed; > alias instance TUnit(T, 1, 0, -2).Unit Acceleration; > const Length meter = {100}; > const Time second = {1}; > } > // all operations below should be statically verified > instance TUnits(double).Acceleration a = 2 * meter / (second * second); > instance TUnits(double).Length l = 10 * meter; > instance TUnits(double).Speed s = a * l; I just don't get where the arguments for implicit come from? > > This kind of expressiveness will make D very suitable to reliable, safe, > efficient numeric computing. We could define algorithms in terms of > precision (template parameters) and be able to instantiate different > versions of the algorithm for different precisions, or compute the result > precision from the parameters and the algorithm used (as in dr. Kahan's > paper). > Other issue is how to deal with multiple template versions and code > sharing: > > > template TList(T) { > class List { > public void sort(int delegate(T, T) comparator) { > // code goes here > } > } > } > template TList(T : Comparable) { > /* how can we instantiate the previous definition to create the "Super" > alias? > */ > private alias instance TList(T).List Super; > class List : Super { > public void sort() { > // code goes here > } > } > } > > > With the class definition we can "cheat" and create subclasses of the > earlier definitions, but with plain templates it fails: > > > template TAssert(T) { > public void equals(T expected, T received) { > // code goes here > } > } > template TAssert(T : double) { > public void equals(T expected, T received, double precision) { > // code goes here > } > } > > instance TAssert(double) check; > check.equals(1.001, 1.000, 0.001); // works as expected > check.equals(1.0, 1.0); // fails > > > The second "TAssert" definition is an extension/specialization of the > previous template, it should have all definitions from the earlier template > definition, plus the new ones, overriding accordingly. Some kind of template > inheritance is necessary, either explicit or implicit. Otherwise we'll have > to duplicate the definitions for all specializations. Ok, I understand that one! > I think that these two extensions are important and necessary to both > library writers and user programmers. Also the unification of the type > system, regarding delegates and function pointers, allowing templates with > function parameters. > > Best regards, > Daniel Yokomiso. > > "Time is the best teacher unfortunately it kills all its students." > > > > --- > Outgoing mail is certified Virus Free. > Checked by AVG anti-virus system (http://www.grisoft.com). > Version: 6.0.510 / Virus Database: 307 - Release Date: 14/8/2003 > > |
August 23, 2003 Re: D User Poll | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | Hi, Comments embedded: "Walter" <walter@digitalmars.com> escreveu na mensagem news:bi6qcm$8qf$1@digitaldaemon.com... > > "Daniel Yokomiso" <daniel_yokomiso@yahoo.com.br> wrote in message news:bi6iu9$2u47$1@digitaldaemon.com... [snip] > > In this way (I'm not arguing about the syntax, just the semantics) we > > can say to the compiler: "a matrix can multiply only matrix with a row > size > > equal to its column size.". Perhaps a better syntax would be: > > > > template TMatrix(T, int ROWS, int COLUMNS) { > > class Matrix { > > private T[] data = new T[ROWS * COLUWNS]; > > public Matrix add(Matrix other) { > > // code goes here > > } > > template implicit (N) { > > /* "implicit" is a keyword to make a template with implicit instantiation. > > * we could also use the "this" keyword or whatever, as long as the > > programmer > > * doesn't need to write something like "A instance > > A.TMul(B.columns()).mul(B)" to > > * safely multiply the A and B matrices. > > */ > > alias instance TMatrix(T, COLUMNS, N).Matrix OtherMatrix; > > alias instance TMatrix(T, ROWS, N).Matrix ResultMatrix; > > public ResultMatrix mul(OtherMatrix other) { > > // code goes here > > } > > } > > } > > } > > > > In this case we have some kind of implicit instantiation, but this > kind > > of template mechanism will be available in the next versions of Java and > C#. > > Also almost all statically-typed functional programming languages have > this > > kind of type system. > > The parameters for the "implicit" template should be always statically > > determined from the operation's parameters, in this case the "other" > Matrix > > template instance. > > I don't get it. Is the implicit template a new template within TMatrix? Where does N come from again? The implicit is just a way to say to the compiler: "the following operation is a template inside the TMatrix, but with this parameter N, that must come from the operation's parameters". So N is a the number of columns of OtherMatrix which must have a number of rows equal to the TMatrix COLUMNS parameter. It's just a way to define the matrix multiplication rule from basic math. In D we have templates with parameters that contain definitions inside, they are like modules. Other languages don't use this form of templates, instead relying on type parameters on the definition (e.g. classes or function with an additional parameter). So in other languages we have: class Matrix(T, int ROWS, int COLUMNS) { // the parameters goes to the class private T[] data = new T[ROWS * COLUWNS]; public Matrix add(Matrix other) { // code goes here } public Matrix(T, ROWS, N) mul(N)(Matrix(T, COLUMNS, N) other) { /* the parameter goes to the operation, but must be determinable from the * parameters, in this case the "other" parameter. */ // code goes here } } As you can see there are two levels of templates here, but in the operations the instantiation is implicit (determinable from the parameters) where in the classes must be explicit (so we need to declare Matrix(int, 2, 3) m). Also works the rule that in the result type all template parameters must be defined in either the class or in the operation, and the template parameters used in the parameters must be either new parameters (like N) or constrained by the class parameters (T or COLUMNS). The mul operation only works in matrices that has the element type T and COLUMNS row size, with the N column size unconstrained. > > My other example involving statically-typed units would become: > > > > template TUnit(T, int C, int G, int S) { > > struct Unit { > > private T value; > > public Unit add(Unit other) { > > // code goes here > > } > > template implicit (C1, G1, S1) { > > alias instance TUnit(T, C1, G1, S1).Unit OtherUnit; > > alias instance TUnit(T, C + C1, G + G1, S + S1).Unit > ResultUnit; > > public ResultUnit mul(OtherUnit other) { > > // code goes here > > } > > } > > // other methods here > > } > > } > > template TUnits(T) { > > alias instance TUnit(T, 1, 0, 0).Unit Length; > > alias instance TUnit(T, 0, 1, 0).Unit Mass; > > alias instance TUnit(T, 0, 0, 1).Unit Time; > > alias instance TUnit(T, 1, 0, -1).Unit Speed; > > alias instance TUnit(T, 1, 0, -2).Unit Acceleration; > > const Length meter = {100}; > > const Time second = {1}; > > } > > // all operations below should be statically verified > > instance TUnits(double).Acceleration a = 2 * meter / (second * second); > > instance TUnits(double).Length l = 10 * meter; > > instance TUnits(double).Speed s = a * l; > > I just don't get where the arguments for implicit come from? As I said before, they are determinable from the operation's parameters. In this case OtherUnit constrain the parameters. [snip] > > template TAssert(T) { > > public void equals(T expected, T received) { > > // code goes here > > } > > } > > template TAssert(T : double) { > > public void equals(T expected, T received, double precision) { > > // code goes here > > } > > } > > > > instance TAssert(double) check; > > check.equals(1.001, 1.000, 0.001); // works as expected > > check.equals(1.0, 1.0); // fails > > > > > > The second "TAssert" definition is an extension/specialization of the > > previous template, it should have all definitions from the earlier > template > > definition, plus the new ones, overriding accordingly. Some kind of > template > > inheritance is necessary, either explicit or implicit. Otherwise we'll > have > > to duplicate the definitions for all specializations. > > Ok, I understand that one! > > > I think that these two extensions are important and necessary to both > > library writers and user programmers. Also the unification of the type system, regarding delegates and function pointers, allowing templates with > > function parameters. > > > > Best regards, > > Daniel Yokomiso. > > > > "Time is the best teacher unfortunately it kills all its students." Best regards, Daniel Yokomiso. "You laugh at me because I'm different. I laugh because you are all the same." - Daniel Knode --- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.510 / Virus Database: 307 - Release Date: 14/8/2003 |
August 24, 2003 Re: D User Poll | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Yokomiso | "Daniel Yokomiso" <daniel_yokomiso@yahoo.com.br> wrote in message news:bi7lqj$1mfi$1@digitaldaemon.com... > Hi, > > Comments embedded: > "Walter" <walter@digitalmars.com> escreveu na mensagem > news:bi6qcm$8qf$1@digitaldaemon.com... > > > > "Daniel Yokomiso" <daniel_yokomiso@yahoo.com.br> wrote in message news:bi6iu9$2u47$1@digitaldaemon.com... > > [snip] > > > > In this way (I'm not arguing about the syntax, just the semantics) > we > > > can say to the compiler: "a matrix can multiply only matrix with a row > > size > > > equal to its column size.". Perhaps a better syntax would be: > > > > > > template TMatrix(T, int ROWS, int COLUMNS) { > > > class Matrix { > > > private T[] data = new T[ROWS * COLUWNS]; > > > public Matrix add(Matrix other) { > > > // code goes here > > > } > > > template implicit (N) { > > > /* "implicit" is a keyword to make a template with implicit > instantiation. > > > * we could also use the "this" keyword or whatever, as long as the > > > programmer > > > * doesn't need to write something like "A instance > > > A.TMul(B.columns()).mul(B)" to > > > * safely multiply the A and B matrices. > > > */ > > > alias instance TMatrix(T, COLUMNS, N).Matrix OtherMatrix; > > > alias instance TMatrix(T, ROWS, N).Matrix ResultMatrix; > > > public ResultMatrix mul(OtherMatrix other) { > > > // code goes here > > > } > > > } > > > } > > > } > > > > > > In this case we have some kind of implicit instantiation, but this > > kind > > > of template mechanism will be available in the next versions of Java and > > C#. > > > Also almost all statically-typed functional programming languages have > > this > > > kind of type system. > > > The parameters for the "implicit" template should be always > statically > > > determined from the operation's parameters, in this case the "other" > > Matrix > > > template instance. > > > > I don't get it. Is the implicit template a new template within TMatrix? Where does N come from again? > > The implicit is just a way to say to the compiler: "the following > operation is a template inside the TMatrix, but with this parameter N, that > must come from the operation's parameters". So N is a the number of columns > of OtherMatrix which must have a number of rows equal to the TMatrix COLUMNS > parameter. It's just a way to define the matrix multiplication rule from basic math. I'm totally lost with where N comes from. The parameters are ROWS and COLUMNS, not N. > In D we have templates with parameters that contain definitions inside, > they are like modules. Other languages don't use this form of templates, instead relying on type parameters on the definition (e.g. classes or function with an additional parameter). So in other languages we have: > > > class Matrix(T, int ROWS, int COLUMNS) { > // the parameters goes to the class > private T[] data = new T[ROWS * COLUWNS]; > public Matrix add(Matrix other) { > // code goes here > } > public Matrix(T, ROWS, N) mul(N)(Matrix(T, COLUMNS, N) other) { > > /* the parameter goes to the operation, but must be determinable from the > * parameters, in this case the "other" parameter. > */ > // code goes here > } > } > > > As you can see there are two levels of templates here, but in the > operations the instantiation is implicit (determinable from the parameters) > where in the classes must be explicit (so we need to declare Matrix(int, 2, > 3) m). Also works the rule that in the result type all template parameters must be defined in either the class or in the operation, and the template parameters used in the parameters must be either new parameters (like N) or > constrained by the class parameters (T or COLUMNS). The mul operation only works in matrices that has the element type T and COLUMNS row size, with the > N column size unconstrained. > > > > My other example involving statically-typed units would become: > > > > > > template TUnit(T, int C, int G, int S) { > > > struct Unit { > > > private T value; > > > public Unit add(Unit other) { > > > // code goes here > > > } > > > template implicit (C1, G1, S1) { > > > alias instance TUnit(T, C1, G1, S1).Unit OtherUnit; > > > alias instance TUnit(T, C + C1, G + G1, S + S1).Unit > > ResultUnit; > > > public ResultUnit mul(OtherUnit other) { > > > // code goes here > > > } > > > } > > > // other methods here > > > } > > > } > > > template TUnits(T) { > > > alias instance TUnit(T, 1, 0, 0).Unit Length; > > > alias instance TUnit(T, 0, 1, 0).Unit Mass; > > > alias instance TUnit(T, 0, 0, 1).Unit Time; > > > alias instance TUnit(T, 1, 0, -1).Unit Speed; > > > alias instance TUnit(T, 1, 0, -2).Unit Acceleration; > > > const Length meter = {100}; > > > const Time second = {1}; > > > } > > > // all operations below should be statically verified > > > instance TUnits(double).Acceleration a = 2 * meter / (second * second); > > > instance TUnits(double).Length l = 10 * meter; > > > instance TUnits(double).Speed s = a * l; > > > > I just don't get where the arguments for implicit come from? > > As I said before, they are determinable from the operation's parameters. > In this case OtherUnit constrain the parameters. I'm also quite lost here as to why this would not instantiate TUnit with infinite recursion. |
August 25, 2003 Re: D User Poll | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | I do not know D, I know C++ a little. I think, I know what Daniel wants. I try to explain in C++ nomenclature (I'll abreviate COLUMNS to COLS): * class Matrix is like C++ template class: template<typename T, int ROWS, int COLS> class Matrix; * class method mull is like C++ member template method of a (templated) class; in C++ it would look like this when defined within Matrix body: template<int N> Matrix<T,ROWS,N> mul(Matrix<T,COLS,N> other); or like this when defined outside of class Matrix: template<typename T, int ROWS, int COLS> template<int N> Matrix<T,ROWS,N> Matrix<T,ROWS,COLS>::mul(Matrix<T,COLS,N> other); * ie Matrix<T,ROWS,COLS> contains potentionally infinite number of methods mul as part of its definition * what is Daniel saying is that in this case explicit instatination of D language is a pain, because you do need not only to explicitly intantiate classes Matrix<T,ROWS,COLS>, Matrix<T,ROWS,N> and Matrix<T,COLS,N> (ie all the matrices used), but also all the methods mul which are possible or better which are used, to multiply these matrices; so Daniel is proposing to introduce implicit instatiations for member templates and template argument deduction for them (he wants [inner] template argument N to be deducted from "other" argument of mul method ... probably the same way as C++ would do it) * as for as infinite recursion problem, I think that here you think too much in a way how you have template explicit instation implemented and Daniel is at a too high level; imagine that Daniel used in his examples keyword painstance instead of instatnce; painstance would not start the whole process of code generation (which would probably result in infinite recursion in your current implementation), but only prepare type to which an alias can be created; the point is that OtherMatrich and ResultMatrix are not part of Matrix template; they are only referenced there with "painstance" :) ... no problem with infinite recursion; there is still a problem with creating instances for all the possible/used mull method for each Matrix type * I'm not sure whether D handles nested templates at all... * the secon example is exactly the same idea, with only one exception and it is that it requires constat expresions to be possible for template arguments, I think this is not possible in C++ (please correct me if I'm wrong), but in C++ you can use an workaround with some enums * the key to understand it is this C++ nomenclature: member template, implicit instantiation, template argument deduction (for [member] function templates) hope this helps "Walter" <walter@digitalmars.com> wrote in message news:bib45j$qos$1@digitaldaemon.com... > [snip] > > > > template TMatrix(T, int ROWS, int COLUMNS) { > > > > class Matrix { > > > > private T[] data = new T[ROWS * COLUWNS]; > > > > public Matrix add(Matrix other) { > > > > // code goes here > > > > } > > > > template implicit (N) { > > > > /* "implicit" is a keyword to make a template with implicit instantiation. > > > > * we could also use the "this" keyword or whatever, as long as the programmer > > > > * doesn't need to write something like "A instance A.TMul(B.columns()).mul(B)" to > > > > * safely multiply the A and B matrices. > > > > */ > > > > alias instance TMatrix(T, COLUMNS, N).Matrix OtherMatrix; here should be painstance :) > > > > alias instance TMatrix(T, ROWS, N).Matrix ResultMatrix; here should be painstance > > > > public ResultMatrix mul(OtherMatrix other) { > > > > // code goes here > > > > } > > > > } > > > > } > > > > } [snip] > > > > template TUnit(T, int C, int G, int S) { > > > > struct Unit { > > > > private T value; > > > > public Unit add(Unit other) { > > > > // code goes here > > > > } > > > > template implicit (C1, G1, S1) { > > > > alias instance TUnit(T, C1, G1, S1).Unit OtherUnit; here should be painstance > > > > alias instance TUnit(T, C + C1, G + G1, S + S1).Unit ResultUnit; here should be painstance > > > > public ResultUnit mul(OtherUnit other) { > > > > // code goes here > > > > } > > > > } > > > > // other methods here > > > > } > > > > } > > > > template TUnits(T) { > > > > alias instance TUnit(T, 1, 0, 0).Unit Length; > > > > alias instance TUnit(T, 0, 1, 0).Unit Mass; > > > > alias instance TUnit(T, 0, 0, 1).Unit Time; > > > > alias instance TUnit(T, 1, 0, -1).Unit Speed; > > > > alias instance TUnit(T, 1, 0, -2).Unit Acceleration; > > > > const Length meter = {100}; > > > > const Time second = {1}; > > > > } > > > > // all operations below should be statically verified > > > > instance TUnits(double).Acceleration a = 2 * meter / (second * second); > > > > instance TUnits(double).Length l = 10 * meter; > > > > instance TUnits(double).Speed s = a * l; [snip] |
Copyright © 1999-2021 by the D Language Foundation