Thread overview | ||||||
---|---|---|---|---|---|---|
|
July 05, 2003 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(); } 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(); } |
July 06, 2003 Re: A couple of template ideas | ||||
---|---|---|---|---|
| ||||
Posted in reply to Patrick Down | 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 |
July 07, 2003 Re: A couple of template ideas | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Yokomiso | 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 |
July 07, 2003 Re: A couple of template ideas | ||||
---|---|---|---|---|
| ||||
Posted in reply to Patrick Down | 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; |
Copyright © 1999-2021 by the D Language Foundation