www.digitalmars.com         C & C++   DMDScript  

D - Deimos Template Library release

reply "Daniel Yokomiso" <daniel_yokomiso yahoo.com.br> writes:
Hi,

    I'm releasing version 0.0.1 of the Deimos Template Library for D, under
the LGPL license. This initial release includes some template array
functions, most of them from Burton Radons' "Array handling" post. Other
stuff in the DTL: Range template classes, RangeSet template classes, a
fraction class and some very simple templates for everyday programming.
    The zip including makefile is available at:

        http://www.minddrome.com/d/deimos/deimos-0.0.1.zip

    It's designed with lots of unit tests and contracts in many functions,
but no documentation currently. Requests for documentation, bugfixes,
enhancements and other stuff will be accepted. I'm planning to release it
via opend.org until next friday, so community work will be available. In the
zip exists a vowels.d file with a simple usage of the library. A make (dmd)
run will execute unittests.
    I intend to work on matrix and numeric libraries in the next couple of
weeks, porting BLAS-like libraries.

    Best regards,
    Daniel Yokomiso.

"I'm not saying there should be a capital punishment for stupidity, but why
don't we just take the safety labels off of everything and let the problem
solve itself?"
Nov 25 2002
next sibling parent "Walter" <walter digitalmars.com> writes:
Cool!

"Daniel Yokomiso" <daniel_yokomiso yahoo.com.br> wrote in message
news:artv39$o0a$1 digitaldaemon.com...
 Hi,

     I'm releasing version 0.0.1 of the Deimos Template Library for D,

 the LGPL license. This initial release includes some template array
 functions, most of them from Burton Radons' "Array handling" post. Other
 stuff in the DTL: Range template classes, RangeSet template classes, a
 fraction class and some very simple templates for everyday programming.
     The zip including makefile is available at:

         http://www.minddrome.com/d/deimos/deimos-0.0.1.zip

     It's designed with lots of unit tests and contracts in many functions,
 but no documentation currently. Requests for documentation, bugfixes,
 enhancements and other stuff will be accepted. I'm planning to release it
 via opend.org until next friday, so community work will be available. In

 zip exists a vowels.d file with a simple usage of the library. A make

 run will execute unittests.
     I intend to work on matrix and numeric libraries in the next couple of
 weeks, porting BLAS-like libraries.

     Best regards,
     Daniel Yokomiso.

 "I'm not saying there should be a capital punishment for stupidity, but

 don't we just take the safety labels off of everything and let the problem
 solve itself?"

Nov 25 2002
prev sibling parent reply "Walter" <walter digitalmars.com> writes:
"Daniel Yokomiso" <daniel_yokomiso yahoo.com.br> wrote in message
news:artv39$o0a$1 digitaldaemon.com...
     I'm releasing version 0.0.1 of the Deimos Template Library for D,

 the LGPL license.

Since you're an expert with both D templates and templates in other languages, I'd be very interested in your opinions on D template "look and feel" compared with C++'s.
Nov 28 2002
parent reply "Daniel Yokomiso" <daniel_yokomiso yahoo.com.br> writes:
"Walter" <walter digitalmars.com> escreveu na mensagem
news:as5r9b$f7j$2 digitaldaemon.com...
 "Daniel Yokomiso" <daniel_yokomiso yahoo.com.br> wrote in message
 news:artv39$o0a$1 digitaldaemon.com...
     I'm releasing version 0.0.1 of the Deimos Template Library for D,

 the LGPL license.

Since you're an expert with both D templates and templates in other languages, I'd be very interested in your opinions on D template "look and feel" compared with C++'s.

Hi, Hey, thanks for the title :-) . My knowledge comes more from studies and reading than from proper coding (I'm a language designer too, so I study lots of languages for my pet language Eon). Well first a brief disclaimer: IMHO C++ is a wonderful language to study, one of the most comprehensive multi-paradigm languages, but is a pain to work with. C++ templates have a wizardry feel to the novice. Template usage is quite simple, implicit instantiation works like magic. But sometimes strange things happen and the reasons for this behavior is difficult to grasp, error messages are cryptic and reading the source codes for the templates is an experts task. To the initiated in template idioms, it still looks like magic, but they can write very powerful templates to solve lots of problems. Papers from http://www.oonumerics.org/oon/#reference are very relevant to understand the capabilities of C++ templates. Most of its power comes from partial instantiation and template specialization. One example from Todd Veldhuizen's 'Template Metaprograms' is the factorial template: template<int N> class Factorial { public: enum {value = N * Factorial<N-1>::value}; }; class Factorial<1> { public: enum {value = 1}; }; This template uses a specialized template version for N = 1, and defines a recursive template that when compiled will compute the factorial. A brilliant usage of this techniques is used in the Blitz++ library (http://www.oonumerics.org/blitz/manual/Frames.html). But reading their sources requires experience with C++. D templates on the other hand are quite easy to write and understand (if you're familiar with generic programming techniques from other languages). But its usage is verbose and sometimes very cumbersome to use. This is a code snippet from DTL (Deimos Template Library) of a Matrix method to calculate the product of two matrices: public Matrix times (Matrix other) in { // rows and columns provide the number of rows and columns of a matrix assert(other.rows() == columns()); } out(result) { assert(rows() == result.rows()); assert(other.columns() == result.columns()); } body { // creates the result matrix Matrix res = new Matrix(rows(), other.columns()); // explicit instantiation of two templates from DTL instance TFunctionalArrays(T, T, T) func2; for (int j = 0; j < other.columns(); j++) { for (int i = 0; i < rows(); i++) { // functional idiom to compute the products of two arrays // ops is a template instance to provide generic basic arithmetic operations // row(int) and column(int) return the selected row and column as an array T[] products = func2.map(row(i), other.column(j), &ops.mul); res.set(i, j, ops.sum(products, zero)); } } return res; } From this code snippet you can see the primary problem with D template syntax: it's difficult to write terse code when you need to refer to explicitly instantiate templates and refer to this template instances through the code. Also current limitations on operator overloading doesn't allow us to use matrices like we use arrays, or to provide numeric operator to numeric arrays. If that was possible we could write: public Matrix times (Matrix other) Matrix res = new Matrix(rows(), other.columns()); firstIndex i; secondIndex j; res[i,j] = sum(row(i) * other.column(j)); return res; } In this example firstIndex and secondIndex are Blitz++-like tensors (http://www.oonumerics.org/blitz/manual/blitz03.html#l75). No need to reference explicitly to TOperations(T) instance (defines sum function and numeric array operators), also no need to explicitly define for-loops or zero value (this is passed as a template value parameter). This version express better the syntax than the first one; The main problem with D template look and feel is that they're too heavy-weight to use. Writing templates in D is easy, but using them has an unnatural feeling. A template function use is different from a regular function use. Statically typed functional programming depends heavily on type inference mechanisms, so the programmer just need to express the algorithm and the compiler can safely determine the types of the expressions. A simple function composition ( . is defines, in most functional languages the function composition operator) is expressed as (Haskell prelude definitions): (.) :: (b -> c) -> (a -> b) -> (a -> c) (f . g) x = f (g x) It's powerful because it's generic, expressive and safe to use. The programmer just write '((3+).(5*)) 6' and the compiler figures out the rest (the expression value is 33, if someone is curious). If the programmer was required to write explicit references to the function composition operator, instead of a simple dot notation, there is a higher chance of the programmer rewriting the code to avoid the complications. In DTL we have two simple functions first and rest that operates on arrays, giving respectively array[0] and array[1..array.length]. If I need to write: instance TArrays(char) arrays; printf("first is '%c' and the rest is '%.*s'\r\n", arrays.first(text), arrays.rest(text)); I'll probably won't bother using it at all and rewrite the code. If instead I can write: printf("first is '%c' and the rest is '%.*s'\r\n", first(text), rest(text)); I'll probably incorporate first and rest in my set of useful tools (because they express the intent not the implementation used). Small templates are useful to reduce code duplication, but they add more complexity than needed. If the template encapsulated complexity is greater than the complexity of thinking about explicit instantiation and explicit references, then it'll be used. My conclusion is that C++ template writing has a different feel than regular C++ coding, but they can be used naturally in the language. D goes the other way around. The good news is that C++ templates cannot be easily repaired to be simple for both users and library writers. But D templates can be made simple for both (IME they're already simple for library writers). The most important problems needing addressing right now are explicit template instance reference and explicit instantiation. Explicit instantiation is not a problem if D supports implicit type inference a la Haskell. There is a very good post about generic programming (with type classes) in Haskell on http://groups.google.com/groups?q=g:thl953488923d&dq=&hl=en&lr=&ie=UTF-8&sel m=93i9qa-1l.ln%40ID-7776.user.dfncis.de . In brief the example is translated to D as: module ai; template AI(A, A (*add)(A,A)) { // the first template parameter is a type, the second is a function A twice(A a) { return add(a, a); } } module client; import ai; instance AI(int, +); // declares that when A is an int, add is the + operation instance AI(T[], ~); // declares that when an array of any type T is used as A, add is the ~ operation; example1 = twice(4); // example1 == 8 example2 = twice("xyz") // example2 == "xyzxyz" This syntax is less cumbersome and more expressive than the current one. It addresses both explicit referencing of template instances, partial instantiation and template constant parameters (in this case functions, but any other value could be used). The problems of template specialization are not addressed, but another syntax could be defined for it. Now if we drop the instance and template keywords, and reuse the module and import keyword we could have: module aiAI(A, A (*add)(A,A)); // a parametrized module, just like a template A twice(A a) { return add(a, a); } module client; import ai(int, +); import ai(T[], ~); example1 = twice(4); // example1 == 8 example2 = twice("xyz") // example2 == "xyzxyz" which is more concise and as clear as the previous. I hope this comparison is useful. But C++ templates aren't the only genericity mechanism we can compare D to, trying to improve it. When we are talking about statically type-safe templates we can point to either Haskell or ML on the functional side, or we can look on Ada 95 or Eiffel (Sather is also good, but it is inactive right now). I don't think we can have all the power of C++ templates without its problems, but if we can have some of its power (say ~70%) and few of its complexity (< 10%) we will be able to provide value to programmers searching for a efficient high-level language. Best regards, Daniel Yokomiso. "Common sense is that layer of prejudices which we acquire before we are sixteen." - Albert Einstein
Nov 28 2002
parent reply "Walter" <walter digitalmars.com> writes:
"Daniel Yokomiso" <daniel_yokomiso yahoo.com.br> wrote in message
news:as6fmc$14ma$1 digitaldaemon.com...
     C++ templates have a wizardry feel to the novice. Template usage is
 quite simple, implicit instantiation works like magic.

Working like magic always made me uncomfortable, I always need to know just what is going on under the hood with any construct I use. C++ templates do a good job of obfuscating what is happening, which makes me very reluctant to use C++ templates for production code (and I know many shops where template use is strongly discouraged because of the high degree of difficulty walking through the code and verifying that it is doing what you want it to do).
 But sometimes strange
 things happen and the reasons for this behavior is difficult to grasp,

 messages are cryptic and reading the source codes for the templates is an
 experts task.

Yes. I believe that the power can be made available without needing to be an expert.
 To the initiated in template idioms, it still looks like
 magic, but they can write very powerful templates to solve lots of

 Papers from http://www.oonumerics.org/oon/#reference are very relevant to
 understand the capabilities of C++ templates. Most of its power comes from
 partial instantiation and template specialization.

Yes. Partial instantiation and specialization are brilliant, and why D templates do that too!
  D templates on the other hand are quite easy to write and understand (if
 you're familiar with generic programming techniques from other languages).
 But its usage is verbose and sometimes very cumbersome to use. This is a
 code snippet from DTL (Deimos Template Library) of a Matrix method to
 calculate the product of two matrices:

 public Matrix times (Matrix other)
 in {
 // rows and columns provide the number of rows and columns of a matrix
     assert(other.rows() == columns());
 } out(result) {
     assert(rows() == result.rows());
     assert(other.columns() == result.columns());
 } body {
 // creates the result matrix
     Matrix res = new Matrix(rows(), other.columns());
 // explicit instantiation of two templates from DTL
     instance TFunctionalArrays(T, T, T) func2;
     for (int j = 0; j < other.columns(); j++) {
         for (int i = 0; i < rows(); i++) {

 // functional idiom to compute the products of two arrays
 // ops is a template instance to provide generic basic arithmetic

 // row(int) and column(int) return the selected row and column as an array
             T[] products = func2.map(row(i), other.column(j), &ops.mul);

             res.set(i, j, ops.sum(products, zero));
         }
     }
     return res;
 }

     From this code snippet you can see the primary problem with D template
 syntax: it's difficult to write terse code when you need to refer to
 explicitly instantiate templates and refer to this template instances
 through the code.

You can inline replace the func2.map(...) with instance TFunctionalArrays(T, T, T).map(...) which isn't too much more verbose than C++: TFunctionalArrays<T, T, T>(...)
 Also current limitations on operator overloading doesn't
 allow us to use matrices like we use arrays, or to provide numeric

 to numeric arrays.

Yes, that should be improved.
 The main problem with D template look and feel is that they're too
 heavy-weight to use. Writing templates in D is easy, but using them has an
 unnatural feeling. A template function use is different from a regular
 function use.

Yes, though that can be mitigated by using an alias: alias instance Foo(T).bar mybar;
 In DTL we have two simple
 functions first and rest that operates on arrays, giving respectively
 array[0] and array[1..array.length]. If I need to write:

 instance TArrays(char) arrays;
 printf("first is '%c' and the rest is '%.*s'\r\n", arrays.first(text),
 arrays.rest(text));

 I'll probably won't bother using it at all and rewrite the code. If

 I can write:

 printf("first is '%c' and the rest is '%.*s'\r\n", first(text),

 I'll probably incorporate first and rest in my set of useful tools

 they express the intent not the implementation used).

Point taken.
 Small templates are
 useful to reduce code duplication, but they add more complexity than

 If the template encapsulated complexity is greater than the complexity of
 thinking about explicit instantiation and explicit references, then it'll

 used.

I agree - but is it really a good idea to use templates for trivial operations? I had to maintain a project once where the guy used a swath of templates, with < and > all over the place. After spending considerable time going through ten thousand lines of this, I finally realized that all he was doing was a simple linked list. It got replace with ->next, and the code got a lot easier to read, and the number of lines of code dropped significantly too <g>.
     My conclusion is that C++ template writing has a different feel than
 regular C++ coding, but they can be used naturally in the language. D goes
 the other way around. The good news is that C++ templates cannot be easily
 repaired to be simple for both users and library writers.

I agree it is beyond repair.
 But D templates
 can be made simple for both (IME they're already simple for library
 writers). The most important problems needing addressing right now are
 explicit template instance reference and explicit instantiation. Explicit
 instantiation is not a problem if D supports implicit type inference a la
 Haskell. There is a very good post about generic programming (with type
 classes) in Haskell on

 m=93i9qa-1l.ln%40ID-7776.user.dfncis.de . In brief the example is

 to D as:

 module ai;
 template AI(A, A (*add)(A,A)) {
 // the first template parameter is a type, the second is a function
    A twice(A a) {
        return add(a, a);
    }
 }

 module client;
 import ai;

 instance AI(int, +);
 // declares that when A is an int, add is the + operation
 instance AI(T[], ~);
 // declares that when an array of any type T is used as A, add is the ~
 operation;

 example1 = twice(4);
 // example1 == 8

 example2 = twice("xyz")
 // example2 == "xyzxyz"


     This syntax is less cumbersome and more expressive than the current

 It addresses both explicit referencing of template instances, partial
 instantiation and template constant parameters (in this case functions,

 any other value could be used). The problems of template specialization

 not addressed, but another syntax could be defined for it. Now if we drop
 the instance and template keywords, and reuse the module and import

 we could have:


 module aiAI(A, A (*add)(A,A));
 // a parametrized module, just like a template
 A twice(A a) {
    return add(a, a);
 }

 module client;
 import ai(int, +);
 import ai(T[], ~);

 example1 = twice(4);
 // example1 == 8

 example2 = twice("xyz")
 // example2 == "xyzxyz"


 which is more concise and as clear as the previous.

I'll have to study that some more.
     I hope this comparison is useful. But C++ templates aren't the only
 genericity mechanism we can compare D to, trying to improve it. When we

 talking about statically type-safe templates we can point to either

 or ML on the functional side, or we can look on Ada 95 or Eiffel (Sather

 also good, but it is inactive right now). I don't think we can have all

 power of C++ templates without its problems, but if we can have some of

 power (say ~70%) and few of its complexity (< 10%) we will be able to
 provide value to programmers searching for a efficient high-level

Yes.
Nov 29 2002
next sibling parent reply Evan McClanahan <evan dontSPAMaltarinteractive.com> writes:
Some things.  First, I quite like the idea of templated modules being 
the primary method of template instantiation, although it raises some 
interesting issues which I don't really have time to go into today.  I 
think that we should give the idea some more thought and discussion 
though, before we use it.  I agree with Daniel's statement that the 
syntax seems cumbersome, but I don't think that introducing a lot of 
keywords and behaviors from functional programming is quite the answer 
we're looking for(or at least me).  Then again, i don't have any 
suggestions for cleaning them up, as I haven't written anything with 
templates in D yet.  Need to do that, one of these days, then, I hope, 
I'll have something more useful to say.

To be honest, as more of a practioner programmer than a language 
designer, all I really care about is the non-magic feeling aspect of it, 
and the simplicity of integrating the mechanism with a debugger, 
something that C++ templates, with all of their complexity, generally 
don't have.

Evan

Walter wrote:
 "Daniel Yokomiso" <daniel_yokomiso yahoo.com.br> wrote in message
 news:as6fmc$14ma$1 digitaldaemon.com...
 
    C++ templates have a wizardry feel to the novice. Template usage is
quite simple, implicit instantiation works like magic.

Working like magic always made me uncomfortable, I always need to know just what is going on under the hood with any construct I use. C++ templates do a good job of obfuscating what is happening, which makes me very reluctant to use C++ templates for production code (and I know many shops where template use is strongly discouraged because of the high degree of difficulty walking through the code and verifying that it is doing what you want it to do).
But sometimes strange
things happen and the reasons for this behavior is difficult to grasp,

error
messages are cryptic and reading the source codes for the templates is an
experts task.

Yes. I believe that the power can be made available without needing to be an expert.
To the initiated in template idioms, it still looks like
magic, but they can write very powerful templates to solve lots of

problems.
Papers from http://www.oonumerics.org/oon/#reference are very relevant to
understand the capabilities of C++ templates. Most of its power comes from
partial instantiation and template specialization.

Yes. Partial instantiation and specialization are brilliant, and why D templates do that too!
 D templates on the other hand are quite easy to write and understand (if
you're familiar with generic programming techniques from other languages).
But its usage is verbose and sometimes very cumbersome to use. This is a
code snippet from DTL (Deimos Template Library) of a Matrix method to
calculate the product of two matrices:

public Matrix times (Matrix other)
in {
// rows and columns provide the number of rows and columns of a matrix
    assert(other.rows() == columns());
} out(result) {
    assert(rows() == result.rows());
    assert(other.columns() == result.columns());
} body {
// creates the result matrix
    Matrix res = new Matrix(rows(), other.columns());
// explicit instantiation of two templates from DTL
    instance TFunctionalArrays(T, T, T) func2;
    for (int j = 0; j < other.columns(); j++) {
        for (int i = 0; i < rows(); i++) {

// functional idiom to compute the products of two arrays
// ops is a template instance to provide generic basic arithmetic

operations
// row(int) and column(int) return the selected row and column as an array
            T[] products = func2.map(row(i), other.column(j), &ops.mul);

            res.set(i, j, ops.sum(products, zero));
        }
    }
    return res;
}

    From this code snippet you can see the primary problem with D template
syntax: it's difficult to write terse code when you need to refer to
explicitly instantiate templates and refer to this template instances
through the code.

You can inline replace the func2.map(...) with instance TFunctionalArrays(T, T, T).map(...) which isn't too much more verbose than C++: TFunctionalArrays<T, T, T>(...)
Also current limitations on operator overloading doesn't
allow us to use matrices like we use arrays, or to provide numeric

operator
to numeric arrays.

Yes, that should be improved.
The main problem with D template look and feel is that they're too
heavy-weight to use. Writing templates in D is easy, but using them has an
unnatural feeling. A template function use is different from a regular
function use.

Yes, though that can be mitigated by using an alias: alias instance Foo(T).bar mybar;
In DTL we have two simple
functions first and rest that operates on arrays, giving respectively
array[0] and array[1..array.length]. If I need to write:

instance TArrays(char) arrays;
printf("first is '%c' and the rest is '%.*s'\r\n", arrays.first(text),
arrays.rest(text));

I'll probably won't bother using it at all and rewrite the code. If

instead
I can write:

printf("first is '%c' and the rest is '%.*s'\r\n", first(text),

rest(text));
I'll probably incorporate first and rest in my set of useful tools

(because
they express the intent not the implementation used).

Point taken.
Small templates are
useful to reduce code duplication, but they add more complexity than

needed.
If the template encapsulated complexity is greater than the complexity of
thinking about explicit instantiation and explicit references, then it'll

be
used.

I agree - but is it really a good idea to use templates for trivial operations? I had to maintain a project once where the guy used a swath of templates, with < and > all over the place. After spending considerable time going through ten thousand lines of this, I finally realized that all he was doing was a simple linked list. It got replace with ->next, and the code got a lot easier to read, and the number of lines of code dropped significantly too <g>.
    My conclusion is that C++ template writing has a different feel than
regular C++ coding, but they can be used naturally in the language. D goes
the other way around. The good news is that C++ templates cannot be easily
repaired to be simple for both users and library writers.

I agree it is beyond repair.
But D templates
can be made simple for both (IME they're already simple for library
writers). The most important problems needing addressing right now are
explicit template instance reference and explicit instantiation. Explicit
instantiation is not a problem if D supports implicit type inference a la
Haskell. There is a very good post about generic programming (with type
classes) in Haskell on

http://groups.google.com/groups?q=g:thl953488923d&dq=&hl=en&lr=&ie=UTF-8&sel
m=93i9qa-1l.ln%40ID-7776.user.dfncis.de . In brief the example is

translated
to D as:

module ai;
template AI(A, A (*add)(A,A)) {
// the first template parameter is a type, the second is a function
   A twice(A a) {
       return add(a, a);
   }
}

module client;
import ai;

instance AI(int, +);
// declares that when A is an int, add is the + operation
instance AI(T[], ~);
// declares that when an array of any type T is used as A, add is the ~
operation;

example1 = twice(4);
// example1 == 8

example2 = twice("xyz")
// example2 == "xyzxyz"


    This syntax is less cumbersome and more expressive than the current

one.
It addresses both explicit referencing of template instances, partial
instantiation and template constant parameters (in this case functions,

but
any other value could be used). The problems of template specialization

are
not addressed, but another syntax could be defined for it. Now if we drop
the instance and template keywords, and reuse the module and import

keyword
we could have:


module aiAI(A, A (*add)(A,A));
// a parametrized module, just like a template
A twice(A a) {
   return add(a, a);
}

module client;
import ai(int, +);
import ai(T[], ~);

example1 = twice(4);
// example1 == 8

example2 = twice("xyz")
// example2 == "xyzxyz"


which is more concise and as clear as the previous.

I'll have to study that some more.
    I hope this comparison is useful. But C++ templates aren't the only
genericity mechanism we can compare D to, trying to improve it. When we

are
talking about statically type-safe templates we can point to either

Haskell
or ML on the functional side, or we can look on Ada 95 or Eiffel (Sather

is
also good, but it is inactive right now). I don't think we can have all

the
power of C++ templates without its problems, but if we can have some of

its
power (say ~70%) and few of its complexity (< 10%) we will be able to
provide value to programmers searching for a efficient high-level

language. Yes.

Nov 29 2002
parent "Daniel Yokomiso" <daniel_yokomiso yahoo.com.br> writes:
"Evan McClanahan" <evan dontSPAMaltarinteractive.com> escreveu na mensagem
news:as7d45$2c1v$1 digitaldaemon.com...
 Some things.  First, I quite like the idea of templated modules being
 the primary method of template instantiation, although it raises some
 interesting issues which I don't really have time to go into today.  I
 think that we should give the idea some more thought and discussion
 though, before we use it.  I agree with Daniel's statement that the
 syntax seems cumbersome, but I don't think that introducing a lot of
 keywords and behaviors from functional programming is quite the answer
 we're looking for(or at least me).  Then again, i don't have any
 suggestions for cleaning them up, as I haven't written anything with
 templates in D yet.  Need to do that, one of these days, then, I hope,
 I'll have something more useful to say.

 To be honest, as more of a practioner programmer than a language
 designer, all I really care about is the non-magic feeling aspect of it,
 and the simplicity of integrating the mechanism with a debugger,
 something that C++ templates, with all of their complexity, generally
 don't have.

 Evan

Hi, The idea is not add keywords and behaviors to D from functional languages. But to provide the possibility of a library writer to create functions with functional 'look and feel'. If you check DTL 0.0.1 (http://www.minddrome.com/d/deimos/deimos-0.0.1.zip) you can see working code that uses today's template syntax to provide functions like map, filter, foldl, etc. D should remain a multi-paradigmatic language, like C++, not became a functional language or an OO language. Best regards, Daniel Yokomiso. "Quote me as saying I was mis-quoted." - Groucho Marx
Nov 29 2002
prev sibling parent reply "Daniel Yokomiso" <daniel_yokomiso yahoo.com.br> writes:
Reply embedded.

"Walter" <walter digitalmars.com> escreveu na mensagem
news:as7akt$29fv$1 digitaldaemon.com...

 You can inline replace the
     func2.map(...)
 with
     instance TFunctionalArrays(T, T, T).map(...)
 which isn't too much more verbose than C++:
     TFunctionalArrays<T, T, T>(...)

I know it, but writing 'import TFunctionalArrays(T,T,T);' after the module declarationg and then just using map(...) is as expressive, has no magic feeling and looks like a regular module import and imported function call. That's why I proposed that syntax. [snip]
 The main problem with D template look and feel is that they're too
 heavy-weight to use. Writing templates in D is easy, but using them has


 unnatural feeling. A template function use is different from a regular
 function use.

Yes, though that can be mitigated by using an alias: alias instance Foo(T).bar mybar;

I use lots of alias, specially to make template classes less verbose. But it doesn't work when you have dozens of functions (like in deimos.arrays module). But it's better than nothing. [snip]
 Small templates are
 useful to reduce code duplication, but they add more complexity than

 If the template encapsulated complexity is greater than the complexity


 thinking about explicit instantiation and explicit references, then


 be
 used.

I agree - but is it really a good idea to use templates for trivial operations? I had to maintain a project once where the guy used a swath of templates, with < and > all over the place. After spending considerable

 going through ten thousand lines of this, I finally realized that all he

 doing was a simple linked list. It got replace with ->next, and the code

 a lot easier to read, and the number of lines of code dropped

 too <g>.

It's like people say: you can write Fortran in any language ;-) . Genericity is good, just like classes, high-order functions and dynamic-dispatched methods. But lots of people write unmaintainable code everywhere, whether having templates or not. Java is my usual example of language with lots of duplicated code in libraries. People rewrite dynamic arrays, binary trees, linked lists, primitive holders and even sorting, because the language lacks a genericity mechanism. It's broken beyond repair, because when they add generics (next release IIRC) millions of lines of code will already be written. Anyone thinks JBoss or Jakarta codebase will be completly reviewed and rewritten to support the genericity mechanism? D can be more successful here, because it'll have templates weaved in the basic libraries. Some trivial operations are really trivial but other are just instances of a more abstract generic pattern. Functional programmers are very fond of generic programming, and they can produce very simple and expressive algorithms. Look at STL functional-style programming vs. any functional language. This is a problem of finding the correct abstractions for any problem. If a language is powerful enough some of its users will shoot themselves in the foot. A nice view on this subject is on http://www-users.cs.york.ac.uk/~susan/joke/foot.htm . I'll still use templates in D, even if the syntax doesn't change. I can live with some verbosity, if at least I can write generic code. I prefer the 'module as genericity unit' syntax, mostly because expressive languages has this point of view. As I said in another post we need a better C and D is today a better C. Everything else is sugar ;-) Best regards, Daniel Yokomiso. "The only difference between me and a madman is that I am not mad." - Salvador Dali
Nov 29 2002
parent "Walter" <walter digitalmars.com> writes:
I'm slowly warming to the idea of using 'import' for template instances to
not only instantiate the template, but to put the names into the current
scope.

"Daniel Yokomiso" <daniel_yokomiso yahoo.com.br> wrote in message
news:as8740$1q4m$1 digitaldaemon.com...
 Reply embedded.

 "Walter" <walter digitalmars.com> escreveu na mensagem
 news:as7akt$29fv$1 digitaldaemon.com...

 You can inline replace the
     func2.map(...)
 with
     instance TFunctionalArrays(T, T, T).map(...)
 which isn't too much more verbose than C++:
     TFunctionalArrays<T, T, T>(...)

I know it, but writing 'import TFunctionalArrays(T,T,T);' after the module declarationg and then just using map(...) is as expressive, has no magic feeling and looks like a regular module import and imported function call. That's why I proposed that syntax. [snip]
 The main problem with D template look and feel is that they're too
 heavy-weight to use. Writing templates in D is easy, but using them



 an
 unnatural feeling. A template function use is different from a regular
 function use.

Yes, though that can be mitigated by using an alias: alias instance Foo(T).bar mybar;

I use lots of alias, specially to make template classes less verbose. But it doesn't work when you have dozens of functions (like in

 module). But it's better than nothing.

 [snip]

 Small templates are
 useful to reduce code duplication, but they add more complexity than

 If the template encapsulated complexity is greater than the complexity


 thinking about explicit instantiation and explicit references, then


 be
 used.

I agree - but is it really a good idea to use templates for trivial operations? I had to maintain a project once where the guy used a swath


 templates, with < and > all over the place. After spending considerable

 going through ten thousand lines of this, I finally realized that all he

 doing was a simple linked list. It got replace with ->next, and the code

 a lot easier to read, and the number of lines of code dropped

 too <g>.

It's like people say: you can write Fortran in any language ;-) . Genericity is good, just like classes, high-order functions and dynamic-dispatched methods. But lots of people write unmaintainable code everywhere, whether having templates or not. Java is my usual example of language with lots of duplicated code in libraries. People rewrite dynamic arrays, binary trees, linked lists, primitive holders and even sorting, because the language lacks a genericity mechanism. It's broken beyond repair, because when they add generics (next release IIRC) millions of

 of code will already be written. Anyone thinks JBoss or Jakarta codebase
 will be completly reviewed and rewritten to support the genericity
 mechanism? D can be more successful here, because it'll have templates
 weaved in the basic libraries.
     Some trivial operations are really trivial but other are just

 of a more abstract generic pattern. Functional programmers are very fond

 generic programming, and they can produce very simple and expressive
 algorithms. Look at STL functional-style programming vs. any functional
 language. This is a problem of finding the correct abstractions for any
 problem. If a language is powerful enough some of its users will shoot
 themselves in the foot. A nice view on this subject is on
 http://www-users.cs.york.ac.uk/~susan/joke/foot.htm .
     I'll still use templates in D, even if the syntax doesn't change. I

 live with some verbosity, if at least I can write generic code. I prefer

 'module as genericity unit' syntax, mostly because expressive languages

 this point of view. As I said in another post we need a better C and D is
 today a better C. Everything else is sugar ;-)

     Best regards,
     Daniel Yokomiso.

 "The only difference between me and a madman is that I am not mad."
 - Salvador Dali

Nov 29 2002