digitalmars.D - Some more template syntax sugar
- Reiner Pope (37/37) Aug 28 2006 I think function templates still require too much in the way of type
- Kristian (4/17) Aug 28 2006 [snip]
- Derek Parnell (9/26) Aug 28 2006 It does! At first glance, this looks quite a natural consequence of the ...
- Walter Bright (6/23) Aug 29 2006 I know. The problem is that it is indistinguishable from:
- Kristian (12/31) Aug 29 2006 Can't we make parameter names to be mandatory here?
- Reiner Pope (31/52) Aug 29 2006 Is the solution to this any worse than the current spec's dealing with
- Reiner Pope (42/42) Sep 01 2006 I've thought about this ambiguity and still come to not much more of a
- Kristian (12/55) Sep 01 2006 I still think that it would be good if parameters names would be
- Walter Bright (5/6) Sep 02 2006 1) Lots of people like nameless parameters to implicitly document that
- Reiner Pope (12/14) Sep 02 2006 I thought of that one, and since you want D to work in the same way as C...
- Derek Parnell (10/17) Sep 02 2006 And lots of people like named parameters to explicitly document the mean...
- Don Clugston (8/23) Sep 04 2006 It would be better to be able to explicitly document that the parameter
- Derek Parnell (10/36) Aug 29 2006 Think outside the actual example and see if the concept of doing a
I think function templates still require too much in the way of type annotations. Take the canonical example, sqr: T sqr(T) (T x) { return x*x; } In this example, we have to declare T three times, even though I think this could be inferred. I propose an alternative syntax: auto sqr(x) { return x*x; } which IMHO looks very elegant. Here are the rules more formally: - if a type is missing for an parameter, template this function by that argument. Do this for every parameter. - use type inference (just like auto) to determine the return type, unless it is marked 'void' so, the above code becomes: typeof(__ret) sqr(__t1) ( __t1 x) { auto __ret = x * x; return __ret; } and for more complex examples, auto foo(a, b, c, d) { ... } becomes: typeof(__ret) foo(__t1, __t2, __t3, __t4) ( __t1 a, __t2 b, __t3 c, __t4 d) { ... } and the instantiation rules are as per normal. Cheers, Reiner
Aug 28 2006
On Mon, 28 Aug 2006 15:18:04 +0300, Reiner Pope <reiner.pope REMOVE.THIS.gmail.com> wrote:I think function templates still require too much in the way of type annotations. Take the canonical example, sqr: T sqr(T) (T x) { return x*x; } In this example, we have to declare T three times, even though I think this could be inferred. I propose an alternative syntax: auto sqr(x) { return x*x; } which IMHO looks very elegant.[snip] It looks nice to me too.
Aug 28 2006
On Mon, 28 Aug 2006 22:18:04 +1000, Reiner Pope wrote:I think function templates still require too much in the way of type annotations. Take the canonical example, sqr: T sqr(T) (T x) { return x*x; } In this example, we have to declare T three times, even though I think this could be inferred. I propose an alternative syntax: auto sqr(x) { return x*x; } which IMHO looks very elegant.It does! At first glance, this looks quite a natural consequence of the way the D language is heading. -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocrity!" 29/08/2006 10:59:17 AM
Aug 28 2006
Reiner Pope wrote:I think function templates still require too much in the way of type annotations. Take the canonical example, sqr: T sqr(T) (T x) { return x*x; } In this example, we have to declare T three times, even though I think this could be inferred. I propose an alternative syntax: auto sqr(x) { return x*x; } which IMHO looks very elegant.I know. The problem is that it is indistinguishable from: typedef int x; auto sqr(x); i.e. when x is a typedef and no parameter name is given, or when x is a parameter name and no type is given.
Aug 29 2006
On Tue, 29 Aug 2006 11:22:19 +0300, Walter Bright <newshound digitalmars.com> wrote:Reiner Pope wrote:Can't we make parameter names to be mandatory here? typedef int x; auto sqr(x); //'x' is treated as parameter name auto sqr2(x val, y); //'x' is treated as typedef Hmm, if someone would like to use non-auto return values with function templates, then how about adding '!' to function template names? For example: int myTemplate!(x, y) { return(x < y ? -1 : (x > y ? 1 : 0)); }I think function templates still require too much in the way of type annotations. Take the canonical example, sqr: T sqr(T) (T x) { return x*x; } In this example, we have to declare T three times, even though I think this could be inferred. I propose an alternative syntax: auto sqr(x) { return x*x; } which IMHO looks very elegant.I know. The problem is that it is indistinguishable from: typedef int x; auto sqr(x); i.e. when x is a typedef and no parameter name is given, or when x is a parameter name and no type is given.
Aug 29 2006
Walter Bright wrote:I know. The problem is that it is indistinguishable from: typedef int x; auto sqr(x); i.e. when x is a typedef and no parameter name is given, or when x is a parameter name and no type is given.Is the solution to this any worse than the current spec's dealing with aliases. From the spec:Note: Type aliases can sometimes look indistinguishable from alias declarations: alias foo.bar abc; // is it a type or a symbol? The distinction is made in the semantic analysis pass. Aliases cannot be used for expressions: struct S { static int i; } S s; alias s.i a; // illegal, s.i is an expression alias S.i b; // ok b = 4; // sets S.i to 4If the semantic analysis pass can determine the validity of alias expressions, I would have thought that it could determine the meaning of your example: - if x is defined as a type, then it is a nameless parameter - if not, then it is a templated function Of course, this provides no way of shadowing types, but I'm not sure how much of a problem that is. The alternatives I see aren't as nice, since some syntax modification would be required: 1. Modify the syntax I propose to make it clear that it's a nameless parameter. Basically any additional keyword/symbol could work, but that extra character makes a big difference in use. I think auto sqr(x) { ... } is much nicer than auto sqr( x) { ... } 2. Modify the syntax for nameless parameters. Perhaps something like the functional languages, where _ denotes a nameless parameter: typedef int a; interface Foo { int bar(a); } would then become: typedef int a; interface Foo { int bar(a _); } I like this proposal a lot more, because it follows the functional language idea of _ being a variable eater. But this is going to break much more code, so I'm stuck here. Cheers, Reiner
Aug 29 2006
I've thought about this ambiguity and still come to not much more of a conclusion. However, a few thoughts: (just to clarify my naming, let's call the current system (parameters without names) nameless parameters, and my suggestion (implicit templating) typeless parameters) 1. Nameless parameters are a very small syntactical sugar as opposed to typeless parameters, and I assert that we can do without them. Most of the time, you should name your parameters anyway, so the caller can have a better idea of what they are used for, and if you decide that it is just way to much to type, then you can get away with only two more characters for each parameter: int foo(int, int); becomes int foo(int a, int b); which really isn't much more to type. 2. It would be possible to do a small modification of the typeless parameter syntax to make it grammatically distinct from typeless parameters. For instance, add a ' ' to make it clear: auto sqr( x) {...} While, on the surface, this seems the rights solution, I think it creates a similar mental block as we get with lazy parameters: even though foo( {x();} ); is only three characters more than foo( x() ); you will get people used to 'proper' lazy evaluation (Smug Lisp Weenies) who say that this means D doesn't *really* support it. My point: by using the same typeless syntax that dynamically typed languages use, it appeals much more to fans of those languages. I think that an unmodified syntax is the best approach from a niceness point of view, and if the language were being designed afresh, I would go for that and ban nameless parameters, since I've already said they are hardly useful. However, given that we are not starting afresh, there may be some code out there which uses nameless parameters. I would guess that that code doesn't appear much, and the only places I can imagine it being is in interfaces and in extern declarations. Since interfaces can't have templates, this would be flagged as an error at compile-time, making it easy to find and solve. For extern declarations, I don't know whether templates are permitted, so this *may* cause a problem. Thoughts, anyone? Cheers, Reiner
Sep 01 2006
I still think that it would be good if parameters names would be mandatory. But then again, I always name my parameters. typedef int x; void foo(x); //'x' is a typeless parameter -> this is a function template void foo(x y); //'x' is a typedef -> this is a normal function Would this break too much old code? If so, how about using '!' with templates (as I mentioned earlier)? For example: void foo!(x); //definitely a function template On Fri, 01 Sep 2006 13:10:49 +0300, Reiner Pope <reiner.pope REMOVE.THIS.gmail.com> wrote:I've thought about this ambiguity and still come to not much more of a conclusion. However, a few thoughts: (just to clarify my naming, let's call the current system (parameters without names) nameless parameters, and my suggestion (implicit templating) typeless parameters) 1. Nameless parameters are a very small syntactical sugar as opposed to typeless parameters, and I assert that we can do without them. Most of the time, you should name your parameters anyway, so the caller can have a better idea of what they are used for, and if you decide that it is just way to much to type, then you can get away with only two more characters for each parameter: int foo(int, int); becomes int foo(int a, int b); which really isn't much more to type. 2. It would be possible to do a small modification of the typeless parameter syntax to make it grammatically distinct from typeless parameters. For instance, add a ' ' to make it clear: auto sqr( x) {...} While, on the surface, this seems the rights solution, I think it creates a similar mental block as we get with lazy parameters: even though foo( {x();} ); is only three characters more than foo( x() ); you will get people used to 'proper' lazy evaluation (Smug Lisp Weenies) who say that this means D doesn't *really* support it. My point: by using the same typeless syntax that dynamically typed languages use, it appeals much more to fans of those languages. I think that an unmodified syntax is the best approach from a niceness point of view, and if the language were being designed afresh, I would go for that and ban nameless parameters, since I've already said they are hardly useful. However, given that we are not starting afresh, there may be some code out there which uses nameless parameters. I would guess that that code doesn't appear much, and the only places I can imagine it being is in interfaces and in extern declarations. Since interfaces can't have templates, this would be flagged as an error at compile-time, making it easy to find and solve. For extern declarations, I don't know whether templates are permitted, so this *may* cause a problem. Thoughts, anyone? Cheers, Reiner
Sep 01 2006
Reiner Pope wrote:Thoughts, anyone?1) Lots of people like nameless parameters to implicitly document that the parameter isn't used. 2) Nameless parameters come up an awful lot in C/C++ header files - I think they're expected.
Sep 02 2006
Walter Bright wrote:2) Nameless parameters come up an awful lot in C/C++ header files - I think they're expected.I thought of that one, and since you want D to work in the same way as C and C++ when the syntax is the same, I figure you must keep nameless parameters working in the way they do. That means that we need a modified typeless parameter syntax. I'm not sure which keywords and operators are available, but I think that isn't used. How about just sticking a into the syntax for typeless parameters to make it unambiguous. auto foo( x, y, int) // x and y are typeless parameters, and the third paremeter is nameless. Cheers, Reiner
Sep 02 2006
On Sat, 02 Sep 2006 13:14:31 -0700, Walter Bright wrote:Reiner Pope wrote:And lots of people like named parameters to explicitly document the meaning of the parameters.Thoughts, anyone?1) Lots of people like nameless parameters to implicitly document that the parameter isn't used.2) Nameless parameters come up an awful lot in C/C++ header files - I think they're expected.So what? This is D and not C/C++. If one is going to use a new language then one should be prepared to learn a few new things too. -- Derek Parnell Melbourne, Australia "Down with mediocrity!"
Sep 02 2006
Derek Parnell wrote:On Sat, 02 Sep 2006 13:14:31 -0700, Walter Bright wrote:It would be better to be able to explicitly document that the parameter isn't used. Maybe by reusing the 'null' keyword. int somefunc(int x, uint null) { }Reiner Pope wrote:And lots of people like named parameters to explicitly document the meaning of the parameters.Thoughts, anyone?1) Lots of people like nameless parameters to implicitly document that the parameter isn't used.It would add a lot more pain to converting C header files to D. For example, the Win32 API project, would require over ten thousand changes.2) Nameless parameters come up an awful lot in C/C++ header files - I think they're expected.So what? This is D and not C/C++. If one is going to use a new language then one should be prepared to learn a few new things too.
Sep 04 2006
On Tue, 29 Aug 2006 01:22:19 -0700, Walter Bright wrote:Reiner Pope wrote:Think outside the actual example and see if the concept of doing a simplification can be achieved. I'm sure you can come up with a better syntax for such an obvious improvement. -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocrity!" 30/08/2006 9:09:51 AMI think function templates still require too much in the way of type annotations. Take the canonical example, sqr: T sqr(T) (T x) { return x*x; } In this example, we have to declare T three times, even though I think this could be inferred. I propose an alternative syntax: auto sqr(x) { return x*x; } which IMHO looks very elegant.I know. The problem is that it is indistinguishable from: typedef int x; auto sqr(x); i.e. when x is a typedef and no parameter name is given, or when x is a parameter name and no type is given.
Aug 29 2006