Thread overview
"Modern D Design" :))
Dec 27, 2004
Aleksey Bobnev
Dec 27, 2004
Walter
Dec 30, 2004
Ivan Senji
Jan 30, 2005
Walter
Jan 30, 2005
Ivan Senji
Jan 30, 2005
Walter
Dec 27, 2004
Zz
Jan 07, 2005
Norbert Nemec
Re:
Dec 28, 2004
M
December 27, 2004
Yesterday I tried to get back to idea of using D templates for meta-programming. Last time I tried it there were some serious bugs which made meta-programming if not impossible at all, still very hard to achieve.

This time it turned out to be a fairly easy task. Though C++ specialization is still much more powerful than D's one. Therefore template meta-programming code in C++ is declarative by nature, while in D it seems to be mostly imperative. But due to unique template syntax introduced in D and some other advantages, D code surely looks cleaner, much more compact, and doesn't require any preprocessor macros.

At this time I have only typelists and related meta functions similar to those from famous Loki library, but it already seems to me - D language has a Bright(sorry for a pun) future in area of meta-programming. Possibly with some more improvements to template facility it will beat C++ completely some day.

I ported a simple lisp program, which finds a solution to hanoi tower
problem, both to C++ and D.
Here's an original code(slightly modified code from xlisp examples):
(defun hanoi(n)
 (eval (cons 'progn (transfer "A" "B" "C" n ))))

(defun print-move ( from to )
  (princ "Move Disk From ")
  (princ from)
  (princ " to ")
  (princ to)
  (princ "\n")
  nil)

(defun transfer ( from to via n )
  (cond ((equal n 1) (list (cons 'print-move (list from to))))
    (t (append
            (append (transfer from via to (- n 1)) (list (cons 'print-move
(list from to))))
            (transfer via to from (- n 1))))))

Here's C++ meta-program "port"(via Loki):
#include <iostream>
#include <typeinfo>
#include "TypeList.h"

using namespace std;

struct A
{
    static const char * name()
    {
        return "A";
    }
};

struct B
{
    static const char * name()
    {
        return "B";
    }
};

struct C
{
    static const char * name()
    {
        return "C";
    }
};

template <typename From,typename To>
struct print_move
{
    static void exec()
    {
        cout<<"Move Disk From "<<From::name()<<" to "<<To::name()<<endl;
    }
};

template <typename From,typename To,typename Via, int n>
struct transfer
{
    typedef typename Loki::TL::Append<typename
transfer<From,Via,To,n-1>::type,Loki::Typelist<print_move<From,To>,Loki::Nul
lType> >::Result type0;
    typedef typename Loki::TL::Append<type0,typename
transfer<Via,To,From,n-1>::type>::Result type;
};

template <typename From,typename To,typename Via>
struct transfer<typename From,typename To,typename Via, 1>
{
    typedef Loki::Typelist<print_move<From,To>,Loki::NullType> type;
};

template <typename FnList>
struct eval
{
};

template <typename Fn,typename Fns>
struct eval <Loki::Typelist<Fn,Fns> >
{
    static void exec()
    {
        Fn::exec();
        eval<Fns>::exec();
    }
};

template <>
struct eval <Loki::NullType>
{
    static void exec()
    {
    }
};

int main()
{
    eval<typename transfer<A,B,C,3>::type>::exec();
}

And here's D port (via my crazy little library):
import Thor.typelist;
import Thor.meta;
import std.stdio;

class A{}
class B{}
class C{}

template PrintMove(From,To)
{
    struct PrintMove
    {
        static void eval()
        {
            writef("Move Disk From %s to
%s\n",typeid(From).toString(),typeid(To).toString());
        }
    }
}

template Transfer(From,To,Via,int n : 1)
{
    alias TL!(PrintMove!(From,To)) Transfer;
}

template Transfer(From,To,Via,int n)
{
    alias
Append!(Append!(.Transfer!(From,Via,To,n-1),TL!(PrintMove!(From,To))),
                  .Transfer!(Via,To,From,n-1)) Transfer;
}

template Eval(TL_ : TypeList)
{
    void Eval()
    {
        TL_.H.eval();
        .Eval!(TL_.T)();
    }
}

template Eval(T : NullT)
{
    void Eval()
    {
    }
}

void main()
{
    Eval!(Transfer!(A,B,C,3))();
}

Now to implementation details. Here is how my TypeList looks and
works(complete code may be found in attachment along with hanoi sample in
C++,
lisp and prolog):

// end of list marker type
class NullT
{
}

// common base type for all typelists
class TypeList
{
    alias NullT H;
    alias NullT T;
    template Length()
    {
        const int Length = 0;
    }
}

// 1-type typelist constructor
template TL(T0)
{
    class TL : TypeList
    {
        public:
        alias T0 H;
        alias NullT T;
        template Length()
        {
            const int Length = 1;
        }
    }
}

// 2-type length typelist
template TL(T0,T1)
{
    class TL : TypeList
    {
        public:
        alias T0 H;
        alias .TL!(T1) T;
        template Length()
        {
            const int Length = 2;
        }
    }
}

// generated constructors for any arbitary number of types
// ...
//

//  Cons is similar to cons in lisp
/*
    Construct type list from head and tail
    typical use :
    Cons!(A,Cons!(B,Cons!(C,NullT)))
*/
template Cons(_Head, _Tail : TypeList)
{
    class Cons : TypeList
    {
        alias _Head H;
        alias _Tail T;
        template Length()
        {
            const int Length = 1 + .Length!(T);
        }
    }
}

template Cons(_Head : NullT, _Tail : TypeList)
{
    class Cons : TypeList
    {
        alias _Tail.H H;
        alias _Tail.T T;
        template Length()
        {
            const int Length = .Length!(_Tail);
        }
    }
}

template Cons(_Head, _Tail : NullT)
{
    class Cons : TypeList
    {
        alias _Head H;
        alias _Tail T;
        template Length()
        {
            const int Length = 1;
        }
    }
}

/*
       General meta-functions
*/

template Equal(T0,T1)
{
    const bool Equal = false;
}

template Equal(T0,T1 : T0)
{
    const bool Equal = true;
}

template SelectType(bool c, T0,T1)
{
    alias T0 SelectType;
}

template SelectType(bool c : false, T0,T1)
{
    alias T1 SelectType;
}

template SelectAlias(bool c, alias T0,alias T1)
{
    alias T0 SelectAlias;
}

template SelectAlias(bool c : false, alias T0, alias T1)
{
    alias T1 SelectAlias;
}

/*
    typelist manipulation
*/
template Length(_TL : TypeList)
{
    const int Length = 1 + .Length!(_TL.T);
}

template Length(_TL : NullT)
{
    const int Length = 0;
}


template RemoveAll(_TL : TypeList, T)
{
    alias SelectType!(Equal!(_TL.H,T),.RemoveAll!(_TL.T,T),
                                      .Cons!(_TL.H,.RemoveAll!(_TL.T,T))
                     ) RemoveAll;
}

template RemoveAll(_TL : NullT, T)
{
    alias NullT RemoveAll;
}

template RemoveAll(_TL, T : NullT)
{
    alias _TL RemoveAll;
}

template Remove(_TL : TypeList, T)
{
    alias SelectType!(Equal!(_TL.H,T),_TL.T,
                                      .Cons!(_TL.H,.Remove!(_TL.T,T))
                     ) Remove;
}

template Remove(_TL : NullT, T)
{
    alias NullT Remove;
}

template Remove(_TL, T : NullT)
{
    alias _TL Remove;
}

template IndexOf(_TL : NullT, T, int i = 0)
{
    const int IndexOf = -1;
}

template IndexOf(_TL : TypeList, T, int i = 0)
{
    const int IndexOf = .Equal!(_TL.H,T) ? i  : .IndexOf!(_TL.T,T,i + 1);
}

template TypeAt(_TL : NullT, int i)
{
    static assert(0);
}

template TypeAt(_TL : TypeList, int i : 0)
{
    alias _TL.H TypeAt;
}

template TypeAt(_TL : TypeList, int i)
{
    alias .TypeAt!(_TL.T,i - 1) TypeAt;
}

template TypeAtNonStrict(_TL : NullT, int i, _Default = NullT)
{
    alias _Default TypeAtNonStrict;
}

template TypeAtNonStrict(_TL : TypeList, int i : 0, _Default = NullT)
{
    alias _TL.H TypeAtNonStrict;
}

template TypeAtNonStrict(_TL : TypeList, int i, _Default = NullT)
{
    alias .TypeAtNonStrict!(_TL.T,i - 1,_Default) TypeAtNonStrict;
}

template Append(_TL0 : TypeList, _TL1: TypeList)
{
    alias Cons!(_TL0.H,.Append!(_TL0.T,_TL1)) Append;
}

template Append(T: NullT, _T : TypeList)
{
    alias _T Append;
}

template Append(T: NullT, _T : NullT)
{
    alias NullT Append;
}

template NoDups(_TL : TypeList)
{
    alias Cons!(_TL.H,Remove!(.NoDups!(_TL.T),_TL.H)) NoDups;
}

template NoDups(_T : NullT)
{
    alias NullT NoDups;
}

template TypeidPrint(_TL : TypeList)
{
    void TypeidPrint()
    {
        typeid(_TL.H).print();
        .TypeidPrint!(_TL.T)();
    }
}

template TypeidPrint(_T)
{
    void TypeidPrint()
    {
        typeid(_T).print();
    }
}

template TypeidPrint(_TL : NullT)
{
    void TypeidPrint()
    {
    }
}

/*
    and finally a little sanity test
*/
alias TL!(int,float,char,double) tl0;
alias TL!(double,char,float,uint) tl1;
alias Append!(tl0,tl1) tl2;
alias NoDups!(tl2) tl3;

template TypeidPrint(_TL : TypeList)
{
    void TypeidPrint()
    {
        typeid(_TL.H).print();
        .TypeidPrint!(_TL.T)();
    }
}

template TypeidPrint(_T)
{
    void TypeidPrint()
    {
        typeid(_T).print();
    }
}

template TypeidPrint(_TL : NullT)
{
    void TypeidPrint()
    {
    }
}

void main()
{
    static assert(IndexOf!(tl0,char) == 2);
    static assert(IndexOf!(tl0,TypeAt!(tl0,IndexOf!(tl0,char))) == 2);
    static
assert(IndexOf!(tl0,TypeAtNonStrict!(tl0,IndexOf!(tl0,uint),char)) == 2);
    printf("tl0.l == %d\ntl1.l == %d\ntl2.l == %d\ntl3.l = %d\n",
            tl0.Length!(),tl1.Length!(),tl2.Length!(),tl3.Length!());
    printf("types in tl0\n");
    TypeidPrint!(tl0)();
    printf("types in tl1\n");
    TypeidPrint!(tl1)();
    printf("types in tl2\n");
    TypeidPrint!(tl2)();
    printf("types in tl3\n");
    TypeidPrint!(tl3)();
}



December 27, 2004
"Aleksey Bobnev" <uw@front.ru> wrote in message news:cqp7v0$1grl$1@digitaldaemon.com...
> This time it turned out to be a fairly easy task. Though C++
specialization
> is still much more powerful than D's one. Therefore template meta-programming code in C++ is declarative by nature, while in D it seems to be mostly imperative. But due to unique template syntax introduced in D and some other advantages, D code surely looks cleaner, much more compact, and doesn't require any preprocessor macros.

Great!

> At this time I have only typelists and related meta functions similar to those from famous Loki library, but it already seems to me - D language
has
> a Bright(sorry for a pun) future in area of meta-programming. Possibly
with
> some more improvements to template facility it will beat C++ completely
some
> day.

What do you think it needs? Also, what in particular are you thinking of by saying that C++ specialization is much more powerful? D's is equivalent, if not more powerful.


December 27, 2004
I could not resist.
As a person who really likes Lisp and D here is a Dylan version.

The code is from the recently released Open Dylan.
I personally used Dylan about 3 years ago for a few projects of my own while
not Lisp it has a small runtime and it statically links.

Module:    hanoi
Synopsis:  The classic Towers of Hanoi puzzle
Author:    Andy Armstrong
Copyright:    Original Code is Copyright (c) 1995-2004 Functional Objects,
Inc.
              All rights reserved.
License:      Functional Objects Library Public License Version 1.0
Dual-license: GNU Lesser General Public License
Warranty:     Distributed WITHOUT WARRANTY OF ANY KIND

define class <disk> (<object>)
  constant slot diameter :: <integer>,
    required-init-keyword: diameter:;
end class <disk>;

define function make-disk
    (integer :: <integer>) => (disk :: <disk>)
  make(<disk>, diameter: integer)
end function make-disk;

define class <tower> (<object>)
  constant slot name :: <string>,
    required-init-keyword: name:;
  constant slot disks :: <deque> = make(<deque>);
end class <tower>;

define method initialize
    (tower :: <tower>,
     #key initial-disks :: <sequence> = #[])
 => ()
  next-method();
  for (disk in initial-disks)
    push(tower.disks, disk)
  end
end method initialize;

define method height
    (tower :: <tower>) => (height :: <integer>)
  size(tower.disks)
end method height;

define variable *n-operations* :: <integer> = 0;

define method move-disk
    (from-tower :: <tower>, to-tower :: <tower>)
  *n-operations* := *n-operations* + 1;
  format-out(".");
  let disk = pop(from-tower.disks);
  push(to-tower.disks, disk)
end method move-disk;

define method hanoi
    (from-tower :: <tower>, to-tower :: <tower>, with-tower :: <tower>,
     #key count :: <integer> = from-tower.height)
 => ()
  if (count >= 1)
    hanoi(from-tower, with-tower, to-tower, count: count - 1);
    move-disk(from-tower, to-tower);
    hanoi(with-tower, to-tower, from-tower, count: count - 1)
  end
end method hanoi;



December 28, 2004
Think the Lisp wins this on ;)

In article <cqp7v0$1grl$1@digitaldaemon.com>, Aleksey Bobnev says...
>
>Yesterday I tried to get back to idea of using D templates for meta-programming. Last time I tried it there were some serious bugs which made meta-programming if not impossible at all, still very hard to achieve.
>
>This time it turned out to be a fairly easy task. Though C++ specialization is still much more powerful than D's one. Therefore template meta-programming code in C++ is declarative by nature, while in D it seems to be mostly imperative. But due to unique template syntax introduced in D and some other advantages, D code surely looks cleaner, much more compact, and doesn't require any preprocessor macros.
>
>At this time I have only typelists and related meta functions similar to those from famous Loki library, but it already seems to me - D language has a Bright(sorry for a pun) future in area of meta-programming. Possibly with some more improvements to template facility it will beat C++ completely some day.
>
>I ported a simple lisp program, which finds a solution to hanoi tower
>problem, both to C++ and D.
>Here's an original code(slightly modified code from xlisp examples):
>(defun hanoi(n)
> (eval (cons 'progn (transfer "A" "B" "C" n ))))
>
>(defun print-move ( from to )
>  (princ "Move Disk From ")
>  (princ from)
>  (princ " to ")
>  (princ to)
>  (princ "\n")
>  nil)
>
>(defun transfer ( from to via n )
>  (cond ((equal n 1) (list (cons 'print-move (list from to))))
>    (t (append
>            (append (transfer from via to (- n 1)) (list (cons 'print-move
>(list from to))))
>            (transfer via to from (- n 1))))))
>
>Here's C++ meta-program "port"(via Loki):
>#include <iostream>
>#include <typeinfo>
>#include "TypeList.h"
>
>using namespace std;
>
>struct A
>{
>    static const char * name()
>    {
>        return "A";
>    }
>};
>
>struct B
>{
>    static const char * name()
>    {
>        return "B";
>    }
>};
>
>struct C
>{
>    static const char * name()
>    {
>        return "C";
>    }
>};
>
>template <typename From,typename To>
>struct print_move
>{
>    static void exec()
>    {
>        cout<<"Move Disk From "<<From::name()<<" to "<<To::name()<<endl;
>    }
>};
>
>template <typename From,typename To,typename Via, int n>
>struct transfer
>{
>    typedef typename Loki::TL::Append<typename
>transfer<From,Via,To,n-1>::type,Loki::Typelist<print_move<From,To>,Loki::Nul lType> >::Result type0;
>    typedef typename Loki::TL::Append<type0,typename
>transfer<Via,To,From,n-1>::type>::Result type;
>};
>
>template <typename From,typename To,typename Via>
>struct transfer<typename From,typename To,typename Via, 1>
>{
>    typedef Loki::Typelist<print_move<From,To>,Loki::NullType> type;
>};
>
>template <typename FnList>
>struct eval
>{
>};
>
>template <typename Fn,typename Fns>
>struct eval <Loki::Typelist<Fn,Fns> >
>{
>    static void exec()
>    {
>        Fn::exec();
>        eval<Fns>::exec();
>    }
>};
>
>template <>
>struct eval <Loki::NullType>
>{
>    static void exec()
>    {
>    }
>};
>
>int main()
>{
>    eval<typename transfer<A,B,C,3>::type>::exec();
>}
>
>And here's D port (via my crazy little library):
>import Thor.typelist;
>import Thor.meta;
>import std.stdio;
>
>class A{}
>class B{}
>class C{}
>
>template PrintMove(From,To)
>{
>    struct PrintMove
>    {
>        static void eval()
>        {
>            writef("Move Disk From %s to
>%s\n",typeid(From).toString(),typeid(To).toString());
>        }
>    }
>}
>
>template Transfer(From,To,Via,int n : 1)
>{
>    alias TL!(PrintMove!(From,To)) Transfer;
>}
>
>template Transfer(From,To,Via,int n)
>{
>    alias
>Append!(Append!(.Transfer!(From,Via,To,n-1),TL!(PrintMove!(From,To))),
>                  .Transfer!(Via,To,From,n-1)) Transfer;
>}
>
>template Eval(TL_ : TypeList)
>{
>    void Eval()
>    {
>        TL_.H.eval();
>        .Eval!(TL_.T)();
>    }
>}
>
>template Eval(T : NullT)
>{
>    void Eval()
>    {
>    }
>}
>
>void main()
>{
>    Eval!(Transfer!(A,B,C,3))();
>}
>
>Now to implementation details. Here is how my TypeList looks and
>works(complete code may be found in attachment along with hanoi sample in
>C++,
>lisp and prolog):
>
>// end of list marker type
>class NullT
>{
>}
>
>// common base type for all typelists
>class TypeList
>{
>    alias NullT H;
>    alias NullT T;
>    template Length()
>    {
>        const int Length = 0;
>    }
>}
>
>// 1-type typelist constructor
>template TL(T0)
>{
>    class TL : TypeList
>    {
>        public:
>        alias T0 H;
>        alias NullT T;
>        template Length()
>        {
>            const int Length = 1;
>        }
>    }
>}
>
>// 2-type length typelist
>template TL(T0,T1)
>{
>    class TL : TypeList
>    {
>        public:
>        alias T0 H;
>        alias .TL!(T1) T;
>        template Length()
>        {
>            const int Length = 2;
>        }
>    }
>}
>
>// generated constructors for any arbitary number of types
>// ...
>//
>
>//  Cons is similar to cons in lisp
>/*
>    Construct type list from head and tail
>    typical use :
>    Cons!(A,Cons!(B,Cons!(C,NullT)))
>*/
>template Cons(_Head, _Tail : TypeList)
>{
>    class Cons : TypeList
>    {
>        alias _Head H;
>        alias _Tail T;
>        template Length()
>        {
>            const int Length = 1 + .Length!(T);
>        }
>    }
>}
>
>template Cons(_Head : NullT, _Tail : TypeList)
>{
>    class Cons : TypeList
>    {
>        alias _Tail.H H;
>        alias _Tail.T T;
>        template Length()
>        {
>            const int Length = .Length!(_Tail);
>        }
>    }
>}
>
>template Cons(_Head, _Tail : NullT)
>{
>    class Cons : TypeList
>    {
>        alias _Head H;
>        alias _Tail T;
>        template Length()
>        {
>            const int Length = 1;
>        }
>    }
>}
>
>/*
>       General meta-functions
>*/
>
>template Equal(T0,T1)
>{
>    const bool Equal = false;
>}
>
>template Equal(T0,T1 : T0)
>{
>    const bool Equal = true;
>}
>
>template SelectType(bool c, T0,T1)
>{
>    alias T0 SelectType;
>}
>
>template SelectType(bool c : false, T0,T1)
>{
>    alias T1 SelectType;
>}
>
>template SelectAlias(bool c, alias T0,alias T1)
>{
>    alias T0 SelectAlias;
>}
>
>template SelectAlias(bool c : false, alias T0, alias T1)
>{
>    alias T1 SelectAlias;
>}
>
>/*
>    typelist manipulation
>*/
>template Length(_TL : TypeList)
>{
>    const int Length = 1 + .Length!(_TL.T);
>}
>
>template Length(_TL : NullT)
>{
>    const int Length = 0;
>}
>
>
>template RemoveAll(_TL : TypeList, T)
>{
>    alias SelectType!(Equal!(_TL.H,T),.RemoveAll!(_TL.T,T),
>                                      .Cons!(_TL.H,.RemoveAll!(_TL.T,T))
>                     ) RemoveAll;
>}
>
>template RemoveAll(_TL : NullT, T)
>{
>    alias NullT RemoveAll;
>}
>
>template RemoveAll(_TL, T : NullT)
>{
>    alias _TL RemoveAll;
>}
>
>template Remove(_TL : TypeList, T)
>{
>    alias SelectType!(Equal!(_TL.H,T),_TL.T,
>                                      .Cons!(_TL.H,.Remove!(_TL.T,T))
>                     ) Remove;
>}
>
>template Remove(_TL : NullT, T)
>{
>    alias NullT Remove;
>}
>
>template Remove(_TL, T : NullT)
>{
>    alias _TL Remove;
>}
>
>template IndexOf(_TL : NullT, T, int i = 0)
>{
>    const int IndexOf = -1;
>}
>
>template IndexOf(_TL : TypeList, T, int i = 0)
>{
>    const int IndexOf = .Equal!(_TL.H,T) ? i  : .IndexOf!(_TL.T,T,i + 1);
>}
>
>template TypeAt(_TL : NullT, int i)
>{
>    static assert(0);
>}
>
>template TypeAt(_TL : TypeList, int i : 0)
>{
>    alias _TL.H TypeAt;
>}
>
>template TypeAt(_TL : TypeList, int i)
>{
>    alias .TypeAt!(_TL.T,i - 1) TypeAt;
>}
>
>template TypeAtNonStrict(_TL : NullT, int i, _Default = NullT)
>{
>    alias _Default TypeAtNonStrict;
>}
>
>template TypeAtNonStrict(_TL : TypeList, int i : 0, _Default = NullT)
>{
>    alias _TL.H TypeAtNonStrict;
>}
>
>template TypeAtNonStrict(_TL : TypeList, int i, _Default = NullT)
>{
>    alias .TypeAtNonStrict!(_TL.T,i - 1,_Default) TypeAtNonStrict;
>}
>
>template Append(_TL0 : TypeList, _TL1: TypeList)
>{
>    alias Cons!(_TL0.H,.Append!(_TL0.T,_TL1)) Append;
>}
>
>template Append(T: NullT, _T : TypeList)
>{
>    alias _T Append;
>}
>
>template Append(T: NullT, _T : NullT)
>{
>    alias NullT Append;
>}
>
>template NoDups(_TL : TypeList)
>{
>    alias Cons!(_TL.H,Remove!(.NoDups!(_TL.T),_TL.H)) NoDups;
>}
>
>template NoDups(_T : NullT)
>{
>    alias NullT NoDups;
>}
>
>template TypeidPrint(_TL : TypeList)
>{
>    void TypeidPrint()
>    {
>        typeid(_TL.H).print();
>        .TypeidPrint!(_TL.T)();
>    }
>}
>
>template TypeidPrint(_T)
>{
>    void TypeidPrint()
>    {
>        typeid(_T).print();
>    }
>}
>
>template TypeidPrint(_TL : NullT)
>{
>    void TypeidPrint()
>    {
>    }
>}
>
>/*
>    and finally a little sanity test
>*/
>alias TL!(int,float,char,double) tl0;
>alias TL!(double,char,float,uint) tl1;
>alias Append!(tl0,tl1) tl2;
>alias NoDups!(tl2) tl3;
>
>template TypeidPrint(_TL : TypeList)
>{
>    void TypeidPrint()
>    {
>        typeid(_TL.H).print();
>        .TypeidPrint!(_TL.T)();
>    }
>}
>
>template TypeidPrint(_T)
>{
>    void TypeidPrint()
>    {
>        typeid(_T).print();
>    }
>}
>
>template TypeidPrint(_TL : NullT)
>{
>    void TypeidPrint()
>    {
>    }
>}
>
>void main()
>{
>    static assert(IndexOf!(tl0,char) == 2);
>    static assert(IndexOf!(tl0,TypeAt!(tl0,IndexOf!(tl0,char))) == 2);
>    static
>assert(IndexOf!(tl0,TypeAtNonStrict!(tl0,IndexOf!(tl0,uint),char)) == 2);
>    printf("tl0.l == %d\ntl1.l == %d\ntl2.l == %d\ntl3.l = %d\n",
>            tl0.Length!(),tl1.Length!(),tl2.Length!(),tl3.Length!());
>    printf("types in tl0\n");
>    TypeidPrint!(tl0)();
>    printf("types in tl1\n");
>    TypeidPrint!(tl1)();
>    printf("types in tl2\n");
>    TypeidPrint!(tl2)();
>    printf("types in tl3\n");
>    TypeidPrint!(tl3)();
>}
>
>
>begin 666 Thor.zip
>M4$L#! H``````)V.FS$````````````````$````8W!P+U!+`P04````" ":
>M9IDQG@N&IJ8!``"^!0``$ ```&-P<"]H86YO:5]C="YC<'"E4TU/@S 8OI/P
>M'][@10T:C;?2D&PSGJ8'LW@U#72N$5I"RZ(Q^^^^!=)ND#FW<5GW]/GBI;T0
>M,BN:G ,52IN:LS(-`P\B).3'#F2^*R[D4@UXN5"WJVTL6B!Q+K2Y745A$ :-
>M1B>0K.2Z8AD'E"06QX@F,S )@Y\P``#<8$9DD"FI#60K5L-U*[N\ZO8MK7]J
>M;II:0C2)D@[<A,%FVW5ZCNMTG^OL'-?9R-7PLBJ8Z6=KY?!4JS)V_Q8J==E5
>M+:1Y+]6:#TNLE<B!?_%L'(X%&T-I](PR>!3ZLPV B%+[2TA7&0E@E$47RF-<
>MYL4)C?WZ3; 8L#1(_Q:F9E(O>>W>P;)SO@2GFJM/0<AB3LBD0BAW24Y+VTCK
>MCFGRYCXEQ'+B7HG+0FA#_< Z`0ZSI[PT16%I*:#TE>NF,&W^77),I[MXW*PO
>MU>;Y9KLIR:G#'$_QWU_A/AT-_/AI'6XO[;7W-?F:%9C[IR+>6NM=*=!!1V1;
>M$J1'W "T):3;2CQH[:GU<GM[#_JPTV HAZL,G.V%*)F0N&^EKLWX,$WB:3R+
>M']PA\E4WOU!+`P04````" #(NM0J$QCZJF "```Y!@``#@```&-P<"].=6QL
>M5'EP92YHM51-;]LP#+T'R']@L\N&9F[788=EIZ ;AFY9D$.+8:="EFB;B"P)
>M^FAK%/WOH[340;L>&\& ;>KQZ>F1TLDKC^GDY 0N.X25W1*LJ/;"#R5X;MW@
>MJ>TBO)7OX.ST] /4`RR-\DBPU'@G\F>0:4=!`:15"$)*VSMA" -$)JZMW2XR
>MYDG2?,=4P>P79WD#Y\?'\!4#M68!W]&@)PD;;ULO^IY,"YRYFX?"EL=&Q,BY
>M`9;.:4(UJUZ07<%2*0K6O/^-0>-0E?0-^IY"(&L@6D@!YR Y=0Z]5=3PFU.B
>MISI%+$L'U!IBWF6P3;P5'J&QGJ>&O1R7O+,!@4$=>F2[6+V)J."68F=3A 9Y
>M'>?M#2E43"=B\4C4]@9!CM)'1F,C29YW#H4',B"TSKALKC [AMK&KGSM&<9$
>MQA31>XWCOO\G#\DYZV-V6UF9>C111$968Y>(Q/OPP,_>4QUPX/8Q;2\,]&*+
>M3 P>G<?P2!#R#E/9ZUY)2!1%39KB`+9YV=M'2RNXB$!A;]U,!/Z?C6RCPWB7
>M%PY9(O6E*8 )<QE*X5]Y3"=%P$J$",DI$7$!/Y)!;KQY:;X,>$.-4=C ^FJU
>MNORS^79]L3Z_YC#'R."S,..-Z#$X(?\=RNGD_A"Z6;74@HU:)ZTO!X<E=!50
>M`5LKP&D6T%FMT)=BS(R%R+#2V;-'<)-T@1M H[CX?LMP,@6I*<0`A] ^G0#
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
>MC&RX7'R5!9K45Q"R%7GP+?KYO\;%_*>]WTS#:TY,AN:<SFB9M"R3#*LFZ0C
>M9 Z<@]OS%TI0D_,QIHV<K@O3K4P?BP_9I"'3U6TJ7'+;W%29NF MY]GO?J_)
>M=!S]U8['S,CSV!EVNDPHYX%5-K.$N 7F7/([$#>H!(Y@`'?&6,L?5JXHYNDH
>MY/[@B_KO:GYJA/Z.S0!7*DK*WE=:GES,(9$%ZHH^S$(68FTYH!.1%436BW_&
>ML4\E3T@*1JS)"573B@*2*572M-BQ"$/QD06XZ!ZBV#Q![&<+<Q9T8<JU$X+6
>M<X7//Z VX:_4<KLW(663.<30#F*X4GIA-]>]MF[^1JP56E70$P>X%=W:0IT?
>MV^ [9"HWV(:H:L*:2=.83(2]*G7[LN9=A%$Y([V1-&9X01_I"8&N\0K?3R6+
>M?!ANKHK*7@>3%"6U9CK*-@FOPJSF,EV8<-U,I#5T306V%UCC9LY\3D/^/VWC
>M7LZG(&@Y1ILF+]?IRPJD?0O2TN3&"3)2-J_(Y 8OPSVJAKNI[*&$.22/K[F.
>M41@OPG Y;] P?!B#<>>)`S TS!T(;VNS!JCWPG$=4^S59A9PR@%V**YA;M+'
>MKP*=227UC_2>!.)CI#ZH091L)NZR1T>HP(J*00:C%%%5RK8RV2@KCITWJ'N-
>M? -PMSSE7(O+=!YR'XYUI?0]&F.1=X+LDE(+GWW4>J19$%+**U^CT)&E@P(R
>MQT5-49NV%C0U5Q%E0&Y+B'+5P![K1?[(SP3[5>^%2Z)X>=7SE")+/?OELH-+
>MW$''5U\S8-XS^-]GZI(^KI[<VV[-GKI#%KZ7X1))'L&'Q_EOO<08608!!%5.
>ML^I^C7#4$W[K]!XE2\TXT&AON["MX[W;/&'/(C#3NO$#>LW'S.VU`;L+Y<*M
>MW0%7Z1;O"C#O>)LE@+9F]NN@1B8U@)N^*VZQF4"4H 5LZ4U6`\UF]ME'?8\U
>ML_I'D#&*@!]5L@#CMY4O@%7+*2,[;BUU`,1VLH<)-L.X(M[:KS8ZZ;CQ7 ,R
>M'T.ZN6-25Q^SX[C&Q-WTULEBS4* 5'V_RF,+$_L:0\W'E[GZ#QX';,WC`X.O
>MUF.#4FD=J*S^KT45I_\/YO35BF[*ZW^!-F&1NC36Q['"3Z:<22K]Z3U>4[]W
>MNO.'",>_X>/V';([EF)&WM]<7G?RQ=9OX-\W7_32##G8JDC[D, L-I%N,:;0
>MP7*+0:+/AFG1MW+'4KP>R#'NY $!T>*@,;(,A;E%F.XF+WX)2P:EEV/IN:$R
>MPM4?2;PR($LVR;"!Q0<#[>6:1).]?(B]Q)ODNBSW\\K]*NE*H8$@-QD4OXLX
>MN62PS&=!U;<#>53.W_KR3,")0/<D&"'9UPC7F7^:$Y;)Y^IOWR&E1O:]!=B6
>M%):7+%WW=F-8K/NTNJU;C$=<P+7QU912@"[Q+]>47],HX %P<:P9&;8W+&1^
>M4G%GN[E]]^;]S>W/KZ\N;FYV<P'ZEK9GF0YJ?3/B[?CRV\)H0_&+%)$.I LI
>M:311=:G*TBV)A0JI<D!I8OU3UU@;6FNV6$2B@]P>X9()"6)!J"+LY+F\ZSRQ
>MB'Q%Z!@WK^[>6DVXC2EB$5H7U>%2X!8GA>5 &DY9*5F6V%N*/*NXE:K,:Q>9
>M'_*[<EK:?M:/F8I_BU8ZB7_=V%E:>#W%F">AF*AHU+^O?GBN?U]]`'?^3V24
>M3M0WVJD$2 F3^O&7&)=^Q+Q_1!*Q]/%4<52O71]"ED/&2!G27-([4);>AT+N
>MY6)!9"86?RA??Z_MFOL?8+0@_K'?Q/=)_^#\^.#H@/PS#43L*8+OOONN"_/
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
>MRK"2\E#78@7W:0A9RD GY.*)&-KZ_4OQ?FUK<I:EPNE"!1[CW=\@=/Z@(O"K
>M-ZB"J*I]<5SQKGQ<%!CFTNJ^1B^S:4,^K:!V"9?DY;/R7+FP5:GE71F3G*,X
>M-W6B'6).]ERR0EY/=B&W5/__OMX.RLBX1]R*"MQLTA"K_S4OJ^2)NZI(F63P
>MYAH4'1T!S:3H3UC$$L0/((M!"ABX$-.$3IED25H5;A-O>]H=,C[HX0!S\@<U
>M\E=5V62P=6$XPZ"VXW6TV>1X%_)PC$&%)VLJM,G)CD3B)(,Z3]?7:9/3W4G%
>M80;5GKU)K4W.=BH8YQG4?/Y6S38YW[5L'&E0^<4&RFUR\0[B<:I!_9\VTV^3
>M3^]C`0XVZ(+G;FP#'FTQ=BDKFH>;M,,S8@>N[:>Q%@(FTYHW,&8+KIWDN382
>M)@.?=VS4'ER[RH2M1$RF1N_$N$VX=I@LV\F8#)_>Z5;LPK7;A-J!D,D4ZYUM
>MS39<.\^Z74B9#,3>^5;MP_4>N;D3,9/IVKO8NHVXWBF%=R-G,JQ[FZ?U+HQQ
>MO5^J[TC09/H?U*3__P!02P$"% `*``````"=CILQ````````````````! ``
>M`````````! `````````8W!P+U!+`0(4`!0````(`)IFF3&>"X:FI@$``+X%
>M```0````````````( ```"(```!C<' O:&%N;VE?8W0N8W!P4$L!`A0`% ``
>M``@`R+K4*A,8^JI@`@``.08```X````````````@````]@$``&-P<"].=6QL
>M5'EP92YH4$L!`A0`% ````@`X+OG,#%:4F@N#@``4X(```X````````````@
>M````@@0``&-P<"]4>7!E3&ES="YH4$L!`A0`% ````@`R+K4*IFQI(4\!@``
>M;A@```\````````````@````W!(``&-P<"]4>7!E36%N:7 N:%!+`0(4`!0`
>M```(`/>$FS$ACR9840$``$(#```'````````````( ```$49``!H86YO:2YD
>M4$L!`A0`% ````@`+;^8,3,.J<'-````XP$```D````````````@````NQH`
>M`&AA;F]I+FQS<%!+`0(4`!0````(`$:^F#%?U[5G`0$``/H!```(````````
>M````( ```*\;``!H86YO:2YP;%!+`0(4``H``````(N.FS$`````````````
>M```%````````````$ ```-8<``!4:&]R+U!+`0(4`!0````(`#R5F3%W%P8W
>M6@$``"8#```+````````````( ```/D<``!4:&]R+VUE=&$N9%!+`0(4`!0`
>M```(`"J/FS$H6*JGAP(``!@'```-````````````( ```'P>``!4:&]R+W1R
>M86ET<RYD4$L!`A0`% ````@`Y**9,0XG:P*K! ``Z",```\````````````@
>L````+B$``%1H;W(O='EP96QI<W0N9%!+!08`````# `,`*L"```&)@``````
>`
>end
>


December 30, 2004
"Walter" <newshound@digitalmars.com> wrote in message news:cqpgh1$1qrs$1@digitaldaemon.com...
>
> "Aleksey Bobnev" <uw@front.ru> wrote in message news:cqp7v0$1grl$1@digitaldaemon.com...

...

>. Possibly
> with
> > some more improvements to template facility it will beat C++ completely
> some
> > day.
>
> What do you think it needs? Also, what in particular are you thinking of
by
> saying that C++ specialization is much more powerful? D's is equivalent,
if
> not more powerful.
>


I know there are people out there that could answer this better than i but i
will try:
Here is the example of C++ code:

<CODE>
#include <iostream>

using namespace std;

template<class U,class V,class X,class Y>
class Four
{
  U i;  V j;  X k;  Y l;
};

template<class U,class V,class X,class Y> int WhatFour(const Four<U,V,X,Y>&
four)
{
  cout << "general template\n";
}

template<class U,class V,class X> int WhatFour(const Four<int,U,V,X>& four)
{
  cout << "specialization:: first int\n";
}

template<class U,class V> int WhatFour(const Four<U,U,V,V>& four)
{
  cout << "specialization:: first two equal, second two equal\n";
}

int main(int argc, char *argv[])
{
  WhatFour(Four<int,float,char,bool>());
  WhatFour(Four<float,float,char,bool>());
  WhatFour(Four<float,float,char,char>());
  WhatFour(Four<int,int,float,char>());
  /*
  will print:
specialization:: first int
general template
specialization:: first two equal, second two equal
specialization:: first int
  */

  return 0;
}

</CODE>

Is there a way to write this in D? If not (and i haven't found one) here is our problem. Specializations like this are used alot in C++.


January 07, 2005
Zz wrote:

> The code is from the recently released Open Dylan.

I know this is drifting off-topic, but still: what is "Open Dylan"? I know of Gwydion and FunctionalDeveloper. The news page of Gwydion mentiones that FD might become OpenDylan one day, but information generally seems rather confusing.

January 30, 2005
"Ivan Senji" <ivan.senji@public.srce.hr> wrote in message news:cr0f07$2uj7$1@digitaldaemon.com...
> Is there a way to write this in D? If not (and i haven't found one) here
is
> our problem. Specializations like this are used alot in C++.

Ah, I see. What you're asking for is not specialization, but implict instantiation of function templates. You can do the same sort of specialization, however, in D:


class Four(U, V, X, Y)
{
  U i;  V j;  X k;  Y l;
}

template WhatFour(U,V,X,Y)
{
    void func(Four!(U,V,X,Y) four)
    {
 printf("general template\n");
    }
}

template WhatFour(U:int,V,X,Y)
{
    void func(Four!(int,V,X,Y) four)
    {
 printf("specialization:: first int\n");
    }
}

template WhatFour(U,V:U,X,Y:X)
{
    void func(Four!(U,U,X,X) four)
    {
 printf("specialization:: first two equal, second two equal\n");
    }
}

alias WhatFour!(int,float,char,bool).func whatfour;
alias WhatFour!(float,float,char,bool).func whatfour;
alias WhatFour!(float,float,char,char).func whatfour;
alias WhatFour!(int,int,float,char).func whatfour;

int main()
{
  Four!(int,float,char,bool) f;
  Four!(float,float,char,bool) g;
  Four!(float,float,char,char) h;
  Four!(int,int,float,char) i;

  whatfour(f);
  whatfour(g);
  whatfour(h);
  whatfour(i);

  /*
  will print:
specialization:: first int
general template
specialization:: first two equal, second two equal
specialization:: first int
  */

  return 0;
}




January 30, 2005
"Walter" <newshound@digitalmars.com> wrote in message news:cti6lg$1o0q$1@digitaldaemon.com...
>
> Ah, I see. What you're asking for is not specialization, but implict instantiation of function templates. You can do the same sort of specialization, however, in D:
>
<snip>
>
> int main()
> {
>   Four!(int,float,char,bool) f;
>   Four!(float,float,char,bool) g;
>   Four!(float,float,char,char) h;
>   Four!(int,int,float,char) i;
>
>   whatfour(f);
>   whatfour(g);
>   whatfour(h);
>   whatfour(i);
>
>   /*
>   will print:
> specialization:: first int
> general template
> specialization:: first two equal, second two equal
> specialization:: first int
>   */

Thanks for this example, but i get:

specialization:: first int
general template
general template
specialization:: first int
?

>   return 0;
> }



January 30, 2005
"Ivan Senji" <ivan.senji@public.srce.hr> wrote in message news:ctiav5$1u2e$1@digitaldaemon.com...
> Thanks for this example, but i get:
>
> specialization:: first int
> general template
> general template
> specialization:: first int
> ?

So did I at first. That's a compiler bug, and I fixed it (will appear in
next update). -Walter