www.digitalmars.com         C & C++   DMDScript  

D - A couple of template ideas

reply Patrick Down <pat codemoon.com> writes:
1. Import template items into the local scope.

template foo(T)
{
      T alpha()
      {
      }

      T beta()
      {
      }

}

template bar(T)
{
      T beta()
      {
      }
}


import instance foo(int) fooint;
import instance bar(int) barint;

void func()
{
      // doesn't need fooint.
      int i = alpha(); 

      // error beta is ambiguous
      i = beta();

      // This is ok
      i = barint.beta();
}


2. Functions as parameters to templates

template foo(F : int delegate(int))
{
      void func()
      {
            F(12);
      }
}


3. Add keyword that allows templates to have access to
the instantiation scope. inscope? local? context?


// a.d

template foo(T)
{
      T alpha()
      {
            inscope.beta();
      }
}

// b.d
import a;

void beta()
{
}

instance foo(int) fooint;

void delta()
{
      // calls this modules beta
      fooint.alpha();
}


class Gamma
{
      void beta()
      {
      }

      instance foo(char) foochar; 
}

void fred()
{
      Gamma g = new Gamma();

      // Calls Gamma's beta member
      // 'inscope' becomes synonymous with
      // 'this' when template is instantiated
      // in a class definition. 
      g.foochar.alpha();
}

The class example above becomes a way of doing
mixins using templates.  Implement #1 and #3
and the following works.

class Gamma
{
      void beta()
      {
      }

      import instance foo(char) foochar; 
}

void fred()
{
      Gamma g = new Gamma();

      g.alpha();
}


1. Import template items into the local scope.

template foo(T)
{
      T alpha()
      {
      }

      T beta()
      {
      }

}

template bar(T)
{
      T beta()
      {
      }
}


import instance foo(int) fooint;
import instance bar(int) barint;

void func()
{
      // doesn't need fooint.
      int i = alpha(); 

      // error beta is ambiguous
      i = beta();

      // This is ok
      i = barint.beta();
}


2. Functions as parameters to templates

template foo(F : int delegate(int))
{
      void func()
      {
            F(12);
      }
}


3. Add keyword that allows templates to have access to
the instantiation scope. inscope? local? context?


// a.d

template foo(T)
{
      T alpha()
      {
            inscope.beta();
      }
}

// b.d
import a;

void beta()
{
}

instance foo(int) fooint;

void delta()
{
      // calls this modules beta
      fooint.alpha();
}


class Gamma
{
      void beta()
      {
      }

      instance foo(char) foochar; 
}

void fred()
{
      Gamma g = new Gamma();

      // Calls Gamma's beta member
      // 'inscope' becomes synonymous with
      // 'this' when template is instantiated
      // in a class definition. 
      g.foochar.alpha();
}

The class example above becomes a way of doing
mixins using templates.  Implement #1 and #3
and the following works.

class Gamma
{
      void beta()
      {
      }

      import instance foo(char) foochar; 
}

void fred()
{
      Gamma g = new Gamma();

      g.alpha();
}
Jul 04 2003
parent reply "Daniel Yokomiso" <daniel_yokomiso yahoo.com.br> writes:
Hi,

    Commments embedded.

----- Original Message -----
From: "Patrick Down" <pat codemoon.com>
Newsgroups: D
Sent: Saturday, July 05, 2003 1:48 AM
Subject: A couple of template ideas


 1. Import template items into the local scope.

 template foo(T)
 {
       T alpha()
       {
       }

       T beta()
       {
       }

 }

 template bar(T)
 {
       T beta()
       {
       }
 }


 import instance foo(int) fooint;
 import instance bar(int) barint;

 void func()
 {
       // doesn't need fooint.
       int i = alpha();

       // error beta is ambiguous
       i = beta();

       // This is ok
       i = barint.beta();
 }

AFAICT the compiler isn't very smart to verify if a given call is truly unambiguous, using all possible rules. If it's conservative this feature is almost useless, only reducing a few keystrokes. The complexity needed to resolve the possible ambiguity problems may be equivalent to the complexity of C++'s templates, a reason why D's templates are explicit. In your example there were two templates and two instances. But the rule must be able to handle dozens of templates and instances (including specialized template declarations).
 2. Functions as parameters to templates

 template foo(F : int delegate(int))
 {
       void func()
       {
             F(12);
       }
 }

I agree this should be possible. The type system today is inconsistent, but once it's finished this kind of parametrization should work.
 3. Add keyword that allows templates to have access to
 the instantiation scope. inscope? local? context?


 // a.d

 template foo(T)
 {
       T alpha()
       {
             inscope.beta();
       }
 }

 // b.d
 import a;

 void beta()
 {
 }

 instance foo(int) fooint;

 void delta()
 {
       // calls this modules beta
       fooint.alpha();
 }


 class Gamma
 {
       void beta()
       {
       }

       instance foo(char) foochar;
 }

 void fred()
 {
       Gamma g = new Gamma();

       // Calls Gamma's beta member
       // 'inscope' becomes synonymous with
       // 'this' when template is instantiated
       // in a class definition.
       g.foochar.alpha();
 }

As we can do this easily doing either: template foo(T, beta : void delegate()) { T alpha() { beta(); } } or: template foo(T) { T alpha(void delegate() beta) { beta(); } } I don't think this feature is worth the trouble. It's an example of "evil" dynamic scoping, instead of "good" lexical scoping. Also implicit usage of functions like this can lead to strange bugs: "I changed my module's function name and now my program reverses the output!!". Also we would have to tell the compiler what is the expected type of the implicit functions, which is as verbose as current mechanics. It seems you posted your ideas twice, is that correct? Best regards, Daniel Yokomiso. "Happiness is when what you think, what you say, and what you do are in harmony." - Mohandas Gandi --- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.495 / Virus Database: 294 - Release Date: 30/6/2003
Jul 06 2003
parent reply Patrick Down <Patrick_member pathlink.com> writes:
Hi,

Comments embedded in turn.


"Daniel Yokomiso" <daniel_yokomiso yahoo.com.br> wrote in
news:be9ki5$1cp9$1 digitaldaemon.com: 

 Hi,
 
     Commments embedded.
 
 ----- Original Message -----
 From: "Patrick Down" <pat codemoon.com>
 Newsgroups: D
 Sent: Saturday, July 05, 2003 1:48 AM
 Subject: A couple of template ideas
 
 
 1. Import template items into the local scope.

 template foo(T)
 {
       T alpha()
       {
       }

       T beta()
       {
       }

 }

 template bar(T)
 {
       T beta()
       {
       }
 }


 import instance foo(int) fooint;
 import instance bar(int) barint;

 void func()
 {
       // doesn't need fooint.
       int i = alpha();

       // error beta is ambiguous
       i = beta();

       // This is ok
       i = barint.beta();
 }

AFAICT the compiler isn't very smart to verify if a given call is truly unambiguous, using all possible rules. If it's conservative this feature is almost useless, only reducing a few keystrokes. The complexity needed to resolve the possible ambiguity problems may be equivalent to the complexity of C++'s templates, a reason why D's templates are explicit. In your example there were two templates and two instances. But the rule must be able to handle dozens of templates and instances (including specialized template declarations).

I'll have to think about this one but my initial impression is that if instance bar(int) barint; requires some combinatorial search for the meaning of beta then the import above only adds one more level to the tree. Admittedly a level with many possible branches. However the compiler already has to handle this level of symbol lookup anyway.
 
 2. Functions as parameters to templates

 template foo(F : int delegate(int))
 {
       void func()
       {
             F(12);
       }
 }

I agree this should be possible. The type system today is inconsistent, but once it's finished this kind of parametrization should work.
 3. Add keyword that allows templates to have access to
 the instantiation scope. inscope? local? context?


 // a.d

 template foo(T)
 {
       T alpha()
       {
             inscope.beta();
       }
 }

 // b.d
 import a;

 void beta()
 {
 }

 instance foo(int) fooint;

 void delta()
 {
       // calls this modules beta
       fooint.alpha();
 }


 class Gamma
 {
       void beta()
       {
       }

       instance foo(char) foochar;
 }

 void fred()
 {
       Gamma g = new Gamma();

       // Calls Gamma's beta member
       // 'inscope' becomes synonymous with
       // 'this' when template is instantiated
       // in a class definition.
       g.foochar.alpha();
 }

As we can do this easily doing either: template foo(T, beta : void delegate()) { T alpha() { beta(); } }

Yes this is a good alternative.
 
 
 or:
 
 
 template foo(T) {
     T alpha(void delegate() beta) {
         beta();
     }
 }

While this is functionally the same it's not quite in the sprit of what I was trying to archive. See below.
 
 I don't think this feature is worth the trouble. It's an example of
 "evil" dynamic scoping, instead of "good" lexical scoping. Also
 implicit usage of functions like this can lead to strange bugs: "I
 changed my module's function name and now my program reverses the
 output!!". Also we would have to tell the compiler what is the
 expected type of the implicit functions, which is as verbose as
 current mechanics. 

I agree that the implicit nature of the feature could be problematic. However when you use such templates you should be aware of what they do and what they require. What I was really trying to archive was a way of doing mixins in D. Which I belive would be a very useful addition. References for mixins: http://citeseer.nj.nec.com/246393.html http://www-106.ibm.com/developerworks/java/library/j-djc05133.html http://www.math.luc.edu/~laufer/teaching/473/handouts/AbstractSubclasses.html http://citeseer.nj.nec.com/smaragdakis00mixinbased.html Patrick Down
Jul 07 2003
parent Patrick Down <Patrick_member pathlink.com> writes:
You know I just wasn't thinking.  Mixins may already work in D.

template CountedT(T)
{
class Counted : T
{
int count;

void insert(T.Type item)
{
super.insert(item);
++count;
}

void remove(T.Type item)
{
--count;
super.remove(item);
}
}
}

template ContainerT(T)
{
class Container
{
typedef Type T;

void insert(T item)
{
}

void remove(T item)
{
}
}
}

alias instance CountedT(instance ContainerT(int).ContainerT).Counted
CountedContainer;
Jul 07 2003