digitalmars.D - Simplifying templates
- dfgh (37/37) Nov 29 2008 Warning: this would break existing code.
- BCS (1/1) Nov 29 2008 Please repost as plain text.
- BCS (3/5) Nov 29 2008 On second look: If that was done as plain text then my NG client just me...
- dfgh (2/5) Nov 29 2008 It is plain text. Do you mean a .txt?
- Bill Baxter (6/11) Nov 29 2008 Looked fine over here. The only thing odd about the formatting is
- dfgh (2/17) Nov 29 2008 Yes, I posted from web-news.
- BCS (3/9) Nov 29 2008 See my followup to my self. It would seem that my client managed to inse...
- Bill Baxter (33/59) Nov 29 2008 Actually something similar is possible in current D with string
- BCS (6/35) Nov 29 2008 this works:
- dfgh (8/89) Nov 29 2008 Types are either primitives or capitalized, assuming capitalization conv...
- Michel Fortin (10/10) Nov 29 2008 Interesting. Have you seen the thread I started last Tuesday suggesting
- dfgh (3/18) Nov 30 2008 That is very similar to my idea, except it would allow dynamic typing. W...
- Michel Fortin (13/19) Dec 01 2008 Yes and no. My idea was that such functions would only work at compile
- Sergey Gromov (20/24) Nov 29 2008 It looks nice, and many people already brought this topic up, the
- dfgh (3/31) Nov 30 2008 D was created as a new language, to replace many of the uses of C(++). C...
- Kagamin (1/1) Nov 30 2008 how do you plan to infer types?
- dfgh (2/3) Nov 30 2008 What needs to be inferred? The type would be written wherever it is need...
Warning: this would break existing code. I have an idea for a completely new template syntax that is easier to use and implement. I'll explain it in therms of a hypothetical language called Dscript. Let's start by imagining that Dscript works identically to D 2.0, but it is interpreted and dynamically typed, with eval's (this is not intended to be implemented, and not the main point of this post). Obviously there isn't much of a point to creating two languages with the same syntax, especially since Dscript would be useless for systems programming, contradicting one of the design goals of D. However, there are some things that you can't do if you have static type enforcement. For example, in D this is impossible: template foo(string Type) { invariant foo = eval(Type ~ ".init"); } but it would be legal in Dscript. The point of templates in D is compile-time evaluation of functions and compile-time creation of types, but if Dscript is going to be interpreted, templates will obviously not get instantiated until they are used since I could write: string type = readLine(); writeln(foo!(type)); If they are not going to be evaluated until run-time, they become identical to functions. For syntactic clarity, Dscript could remove templates altogether and replace them with functions: eval(Type) foo(string Type) { return eval(Type ~ ".init"); } If you don't like the idea of the return type being an eval, remember that Dscript is dynamically typed and is not supposed to be implemented. I'm just writing the type to make the next step easier: bringing this back to D. First, we have to eliminate eval. Well, I have only been using it to convert strings into types, so what if we made a type type? type myint = int; //we don't need alias anymore type myOtherInt : int; //or typedef, note the colon type[3] threeIntegers = [short, int, long]; //and tuples are now built-ins // ! syntax is obsolete too, because templates are functions to(myint, 13.7); //and is-expressions are simpler if(int <= float) { writeln("int is cast-able or identical to float."); } if(myint == int) { writeln("myint and int are the same type."); } import std.socket; if(UdpSocket <: Socket) { writeln("UdpSocket extends Socket."); } Everything is so much simpler! This is easier for both programmers and compilers, but we still have one problem: dynamic typing. This isn't too hard to eliminate, though; we just have to make sure that whenever we use a type, it's known at compile time. This checking is already in place, for example integer template parameters are known at compile-time. If necessary, it can also be easily accomplished by making types immutable. What about templates with non-type parameters, such int's? Simple: int bar(string str, static int abc, type T) abc must be known at compile-time, since it is static. T can be regarded as implicitly static, just as str, being declared string instead of char[], is implicitly invariant in D 2.0. A template is instantiated for each unique set of static parameters, giving either a function (pointer), a new type (struct/class), or whatever else could be templated. Now we have our static typing back. The last use of templates is compile-time function evaluation. There is already a better way to do this in D. instead of writing a function twice, once normally, and once confusingly using recursive templates, just say: static int a = baz('a', 5, "asdf"); The static keyword tells it to evaluate at compile time, similar to my proposed use of static. This is recommended, instead of the template approach, at http://www.digitalmars.com/d/2.0/templates-revisited.html, just before the section on SFINAE. We've created a language just like D, except it simplifies alias's, typedef's, tuples, is expressions, and especially templates, all the confusing and hard-to-learn aspects. Instead, we have the much more elegant syntax of types.
Nov 29 2008
Reply to Benjamin,Please repost as plain text.On second look: If that was done as plain text then my NG client just messed up big time!!
Nov 29 2008
BCS Wrote:Please repost as plain text.It is plain text. Do you mean a .txt?
Nov 29 2008
On Sun, Nov 30, 2008 at 7:15 AM, dfgh <dfgh mailinator.com> wrote:BCS Wrote:Looked fine over here. The only thing odd about the formatting is there are no line breaks. But anyway you posted from the web-news interface, right? So it's not a configuration that's under your control in any event. --bbPlease repost as plain text.It is plain text. Do you mean a .txt?
Nov 29 2008
Bill Baxter Wrote:On Sun, Nov 30, 2008 at 7:15 AM, dfgh <dfgh mailinator.com> wrote:Yes, I posted from web-news.BCS Wrote:Looked fine over here. The only thing odd about the formatting is there are no line breaks. But anyway you posted from the web-news interface, right? So it's not a configuration that's under your control in any event. --bbPlease repost as plain text.It is plain text. Do you mean a .txt?
Nov 29 2008
Reply to dfgh,BCS Wrote:See my followup to my self. It would seem that my client managed to insert some content from an RSS item into the NG post space. WT... :bPlease repost as plain text.It is plain text. Do you mean a .txt?
Nov 29 2008
On Sun, Nov 30, 2008 at 6:05 AM, dfgh <dfgh mailinator.com> wrote:Warning: this would break existing code. I have an idea for a completely new template syntax that is easier to use and implement. I'll explain it in therms of a hypothetical language called Dscript. Let's start by imagining that Dscript works identically to D 2.0, but it is interpreted and dynamically typed, with eval's (this is not intended to be implemented, and not the main point of this post). Obviously there isn't much of a point to creating two languages with the same syntax, especially since Dscript would be useless for systems programming, contradicting one of the design goals of D. However, there are some things that you can't do if you have static type enforcement. For example, in D this is impossible: template foo(string Type) { invariant foo = eval(Type ~ ".init"); }Actually something similar is possible in current D with string mixins. But they have to be full statements and not expressions. template foo(string Type) { mixin("invariant foo = "~Type~".init;"); } But it might be nice if string mixins worked for expressions too. I presume there's some reason Walter didn't make them work as expressions, though.Well, I have only been using it to convert strings into types, so what if we made a type type? type myint = int; //we don't need alias anymore type myOtherInt : int; //or typedef, note the colon type[3] threeIntegers = [short, int, long]; //and tuples are now built-ins // ! syntax is obsolete too, because templates are functions to(myint, 13.7); //and is-expressions are simpler if(int <= float) { writeln("int is cast-able or identical to float."); }For this, what you say might be easier for the user (i'm not convinced though, because now when I see if(a<b) I first have to figure out if that's types or values). But some of those are definitely harder for the poor compiler, who has to decide if the stuff inside the if() is working on types or values. So it will have to delay creating the final syntax tree until the semantic pass. Walter won't like this. Also types aren't necessarily an ordered relation in the way that int<=float implies. It could be that both A is implicitly convertible to B and B is implicitly convertible to A, but A!=B. I think that's why is() expressions use the colon for that now rather than the <.if(myint == int) { writeln("myint and int are the same type."); } import std.socket; if(UdpSocket <: Socket) { writeln("UdpSocket extends Socket."); } Everything is so much simpler!How do you replace the versions of 'is' that infer a type and make an alias to it? like if(is(T S : T[]) (or whatever that horrible syntax is.)This is easier for both programmers and compilers, but we still have one problem: dynamic typing. This isn't too hard to eliminate, though; we just have to make sure that whenever we use a type, it's known at compile time. This checking is already in place, for example integer template parameters are known at compile-time. If necessary, it can also be easily accomplished by making types immutable. What about templates with non-type parameters, such int's? Simple: int bar(string str, static int abc, type T)This one looks like the proposal Walter and Andrei discussed at the D 2007 conference. The static int part anyway. I'm not sure they were planning to allow passing types that way or not.We've created a language just like D, except it simplifies alias's, typedef's, tuples, is expressions, and especially templates, all the confusing and hard-to-learn aspects. Instead, we have the much more elegant syntax of types.I kind of like the idea of unifying syntax for manipulating types and values, but it has to be done in such a way that the compiler can still easily parse the result without having to do the semantic analysis to figure out if the expression is about types or not. For instance a while back I was suggesting we use '=' with alias: "alias FloatAlias = float" so that type assignment looks more like value assignment. --bb
Nov 29 2008
Reply to Bill,On Sun, Nov 30, 2008 at 6:05 AM, dfgh <dfgh mailinator.com> wrote:this works: int i = mixin("5"); import std.stdio; void main(){writef("%d\n", i);} http://codepad.org/1a14zKslWarning: this would break existing code. I have an idea for a completely new template syntax that is easier to use and implement. I'll explain it in therms of a hypothetical language called Dscript. Let's start by imagining that Dscript works identically to D 2.0, but it is interpreted and dynamically typed, with eval's (this is not intended to be implemented, and not the main point of this post). Obviously there isn't much of a point to creating two languages with the same syntax, especially since Dscript would be useless for systems programming, contradicting one of the design goals of D. However, there are some things that you can't do if you have static type enforcement. For example, in D this is impossible: template foo(string Type) { invariant foo = eval(Type ~ ".init"); }Actually something similar is possible in current D with string mixins. But they have to be full statements and not expressions. template foo(string Type) { mixin("invariant foo = "~Type~".init;"); }But it might be nice if string mixins worked for expressions too. I presume there's some reason Walter didn't make them work as expressions, though.
Nov 29 2008
Bill Baxter Wrote:On Sun, Nov 30, 2008 at 6:05 AM, dfgh <dfgh mailinator.com> wrote:You're right, I forgot about that feature.Warning: this would break existing code. I have an idea for a completely new template syntax that is easier to use and implement. I'll explain it in therms of a hypothetical language called Dscript. Let's start by imagining that Dscript works identically to D 2.0, but it is interpreted and dynamically typed, with eval's (this is not intended to be implemented, and not the main point of this post). Obviously there isn't much of a point to creating two languages with the same syntax, especially since Dscript would be useless for systems programming, contradicting one of the design goals of D. However, there are some things that you can't do if you have static type enforcement. For example, in D this is impossible: template foo(string Type) { invariant foo = eval(Type ~ ".init"); }Actually something similar is possible in current D with string mixins. But they have to be full statements and not expressions. template foo(string Type) { mixin("invariant foo = "~Type~".init;"); } But it might be nice if string mixins worked for expressions too. I presume there's some reason Walter didn't make them work as expressions, though.Types are either primitives or capitalized, assuming capitalization convention is followed.Well, I have only been using it to convert strings into types, so what if we made a type type? type myint = int; //we don't need alias anymore type myOtherInt : int; //or typedef, note the colon type[3] threeIntegers = [short, int, long]; //and tuples are now built-ins // ! syntax is obsolete too, because templates are functions to(myint, 13.7); //and is-expressions are simpler if(int <= float) { writeln("int is cast-able or identical to float."); }For this, what you say might be easier for the user (i'm not convinced though, because now when I see if(a<b) I first have to figure out if that's types or values).But some of those are definitely harder for the poor compiler, who has to decide if the stuff inside the if() is working on types or values.It no more complex than normal operator overloading, which is supported.So it will have to delay creating the final syntax tree until the semantic pass. Walter won't like this. Also types aren't necessarily an ordered relation in the way that int<=float implies. It could be that both A is implicitly convertible to B and B is implicitly convertible to A, but A!=B. I think that's why is() expressions use the colon for that now rather than the <.Good point, we need better syntax than my proposal. We could make new operators if necessary. Maybe cast-able and implicitly convertible should each have their own syntax. We could stick with is-expressions and still retain the main part of my idea, but I don't like them. Their rules are too different from the syntax of the rest of the language, so they must be learned separately.I forgot that this existed. Anyway, by passing type's with the same syntax as variables we completely eliminate the function/template dichotomy, simplifying the language.if(myint == int) { writeln("myint and int are the same type."); } import std.socket; if(UdpSocket <: Socket) { writeln("UdpSocket extends Socket."); } Everything is so much simpler!How do you replace the versions of 'is' that infer a type and make an alias to it? like if(is(T S : T[]) (or whatever that horrible syntax is.)This is easier for both programmers and compilers, but we still have one problem: dynamic typing. This isn't too hard to eliminate, though; we just have to make sure that whenever we use a type, it's known at compile time. This checking is already in place, for example integer template parameters are known at compile-time. If necessary, it can also be easily accomplished by making types immutable. What about templates with non-type parameters, such int's? Simple: int bar(string str, static int abc, type T)This one looks like the proposal Walter and Andrei discussed at the D 2007 conference. The static int part anyway. I'm not sure they were planning to allow passing types that way or not.To conclude (again), C is based around functions and struct's, Lisp is based around cons's and atoms, Java is based around classes, and Smalltalk is based on messages and classes. Many similar features in D are currently written very differently, preventing it from having the unified feel that these other languages enjoy, and most of the minor, confusing features are caused by an inability to talk about types using the same concepts as data. --SamWe've created a language just like D, except it simplifies alias's, typedef's, tuples, is expressions, and especially templates, all the confusing and hard-to-learn aspects. Instead, we have the much more elegant syntax of types.I kind of like the idea of unifying syntax for manipulating types and values, but it has to be done in such a way that the compiler can still easily parse the result without having to do the semantic analysis to figure out if the expression is about types or not. For instance a while back I was suggesting we use '=' with alias: "alias FloatAlias = float" so that type assignment looks more like value assignment. --bb
Nov 29 2008
Interesting. Have you seen the thread I started last Tuesday suggesting mostly the same thing: treating types like values? I ended up with what looks like a solution to get rid of most uses for templates (replacing them with compile-time-only functions returning types). Look for 'The "type" type dream', starting here: <http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=80077> -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Nov 29 2008
Michel Fortin Wrote:Interesting. Have you seen the thread I started last Tuesday suggesting mostly the same thing: treating types like values? I ended up with what looks like a solution to get rid of most uses for templates (replacing them with compile-time-only functions returning types). Look for 'The "type" type dream', starting here: <http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=80077> -- Michel Fortin michel.fortin michelf.com http://michelf.com/That is very similar to my idea, except it would allow dynamic typing. We do have dynamic typing to some extent in D (Variant's, variadic functions), but it slows down code. I prefer enforcing static typing, especially given D's design goals, such as systems programming. Code that needs dynamic typing is the exception, so it gets Variant's rather than a part of the core language. --Sam
Nov 30 2008
On 2008-11-30 11:00:07 -0500, dfgh <dfgh mailinator.com> said:That is very similar to my idea, except it would allow dynamic typing. We do have dynamic typing to some extent in D (Variant's, variadic functions), but it slows down code. I prefer enforcing static typing, especially given D's design goals, such as systems programming. Code that needs dynamic typing is the exception, so it gets Variant's rather than a part of the core language.Yes and no. My idea was that such functions would only work at compile time (like current CTFE). When mixed with other parameters the part about the types would need to work at compile time, it would create a new function instance for each type argument you give it in the arguments. Basically, it'd behave mostly as current function templates. It has been proposed in that thread that this be extended to dynamic typing, which I agree could be done using the same syntax. But dynamic typing is out of my proposal. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Dec 01 2008
Sat, 29 Nov 2008 16:05:31 -0500, dfgh wrote:Warning: this would break existing code. I have an idea for a completely new template syntax that is easier to use and implement.It looks nice, and many people already brought this topic up, the template-function unification. But some changes may be simply too much. My experience led me to belief that one should not significantly change design during a project. You can tweak, polish, cut sharp corners and drape in different colors, but you shouldn't change the basis. The problem is, you can never tell whether a particular design was wrong until you've implemented a finished product based upon that design. And you can never justify a significant design change because you end up with nothing to compare to. You have nothing to answer to those who say you shouldn't have changed anything, except "maybe." Also, if you do significantly change design, you risk ending up with a half-baked thing nobody wants to use because it's half-baked and changes too often too much. This is what happens to D2 to a certain extent, and you must be really careful now. To put this another way, when a change proposed is so significant, actually getting it into the language becomes much less a matter of proposal quality and usefulness, and much more a matter of Walter's personal opinion. I think that the fate of such proposals is to wait until somebody decides to write another language "better than D." :)
Nov 29 2008
Sergey Gromov Wrote:Sat, 29 Nov 2008 16:05:31 -0500, dfgh wrote:D was created as a new language, to replace many of the uses of C(++). C has an amazing goal: it allows you to do structured programming with high-level concepts while still remaining as close to the machine as possible. C++ sought to improve that by creating further abstractions without losing performance, but C++ was not very well designed. Even in the STL and Boost, there are ugly hacks created to make the language more usable. D exists because people wanted a language like C++, but more elegant. Why stop at only slightly better? D 2.0 is changing quickly, but that is because it is an experiment: what is the best language we can create? D is changing a lot because it is still incomplete and Walter is still trying to perfect it. We don't want a language that people dismiss for being too similar to C++. We don't want a language that, just as it is catching on, will be replaced by someone wanting something "better than D." We want the best of all possible C-like languages. My (and apparently others') proposal is not a huge change is goals, it is just a much clearer syntax that would make D much easier to use. --SamWarning: this would break existing code. I have an idea for a completely new template syntax that is easier to use and implement.It looks nice, and many people already brought this topic up, the template-function unification. But some changes may be simply too much. My experience led me to belief that one should not significantly change design during a project. You can tweak, polish, cut sharp corners and drape in different colors, but you shouldn't change the basis. The problem is, you can never tell whether a particular design was wrong until you've implemented a finished product based upon that design. And you can never justify a significant design change because you end up with nothing to compare to. You have nothing to answer to those who say you shouldn't have changed anything, except "maybe." Also, if you do significantly change design, you risk ending up with a half-baked thing nobody wants to use because it's half-baked and changes too often too much. This is what happens to D2 to a certain extent, and you must be really careful now. To put this another way, when a change proposed is so significant, actually getting it into the language becomes much less a matter of proposal quality and usefulness, and much more a matter of Walter's personal opinion. I think that the fate of such proposals is to wait until somebody decides to write another language "better than D." :)
Nov 30 2008
Kagamin Wrote:how do you plan to infer types?What needs to be inferred? The type would be written wherever it is needed.
Nov 30 2008
dfgh Wrote:Kagamin Wrote:That will be too verbose. May be I misused the term. In http://www.digitalmars.com/d/2.0/template.html it's called argument deduction. See Function Templates section where Square(3) is deduced to be Square!(int)(3). This is a nice feature.how do you plan to infer types?What needs to be inferred? The type would be written wherever it is needed.
Nov 30 2008
And you'd better get acquainted with http://www.digitalmars.com/d/2.0/template.html http://www.digitalmars.com/d/2.0/template-mixin.html http://www.digitalmars.com/d/2.0/templates-revisited.html http://www.digitalmars.com/d/2.0/variadic-function-templates.html http://www.digitalmars.com/d/2.0/template-comparison.html and figure out whether you proposal barely covers all D templates use cases.
Nov 30 2008
Kagamin Wrote:And you'd better get acquainted with http://www.digitalmars.com/d/2.0/template.html http://www.digitalmars.com/d/2.0/template-mixin.html http://www.digitalmars.com/d/2.0/templates-revisited.html http://www.digitalmars.com/d/2.0/variadic-function-templates.html http://www.digitalmars.com/d/2.0/template-comparison.html and figure out whether you proposal barely covers all D templates use cases.I have read all those pages. My proposal would be compatible with them. About your other question, instead of writing: T Square(T)(T t) { return t * t; } writefln("The square of %s is %s", 3, Square(3)); we would write: T Square(type T, T t) { return t * t; } writefln("The square of %s is %s", 3, Square(3)); If a non-type argument is used in place of a type that will occur later in the parameter list, we just skip the type and infer it later. It works just as well as the current approach. If you think it would be too confusing, you can put all your types before any non-types; it would just be syntactic sugar on what we have now. --Sam
Nov 30 2008