www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Template functions, can we make it more simple?

reply "SteveGuo" <steveguo outlook.com> writes:
I'm not an expert on programming language, if I made a naive 
issue, just forgive me:p

Can we declare a template function like this?

auto Add(a, b) // Note a, b do not have type, that means a and b 
use template type
{
     return a + b;
}

auto Sub(a, int b) // a uses template type, b is fixed to int
{
     return a - b;
}

When we call the function,

Add(1, 2); // deduced to be Add(int, int);
Add(1.5, 2.3); // deduced to be Add(double, double);
Add(1.5, "Hello"); // compiler error!

Sub(1.5, 1); // deduced to be Add(double, int);
Sub(1, 1.1); // deduced to be Add(int, int); compiler error, 
double can not converted to int automatically
Aug 02 2013
next sibling parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Friday, 2 August 2013 at 20:34:04 UTC, SteveGuo wrote:
 I'm not an expert on programming language, if I made a naive 
 issue, just forgive me:p
Yes, this would have been better asked in .learn, but no matter.
 Can we declare a template function like this?

 auto Add(a, b) // Note a, b do not have type, that means a and 
 b use template type
 {
     return a + b;
 }

 auto Sub(a, int b) // a uses template type, b is fixed to int
 {
     return a - b;
 }

 When we call the function,

 Add(1, 2); // deduced to be Add(int, int);
 Add(1.5, 2.3); // deduced to be Add(double, double);
 Add(1.5, "Hello"); // compiler error!

 Sub(1.5, 1); // deduced to be Add(double, int);
 Sub(1, 1.1); // deduced to be Add(int, int); compiler error, 
 double can not converted to int automatically
Types can be deduced automatically, so you can simply write: auto Add(A, B)(A a, B b); The type is explicit in the *declaration*, but when you call "add(1, 2)", the compiler will *deduce* A and B to be int. Ditto for sub: auto Sub(A a)(A a, int b);
Aug 02 2013
parent reply "SteveGuo" <steveguo outlook.com> writes:
On Friday, 2 August 2013 at 20:37:55 UTC, monarch_dodra wrote:
 On Friday, 2 August 2013 at 20:34:04 UTC, SteveGuo wrote:
 I'm not an expert on programming language, if I made a naive 
 issue, just forgive me:p
Yes, this would have been better asked in .learn, but no matter.
 Can we declare a template function like this?

 auto Add(a, b) // Note a, b do not have type, that means a and 
 b use template type
 {
    return a + b;
 }

 auto Sub(a, int b) // a uses template type, b is fixed to int
 {
    return a - b;
 }

 When we call the function,

 Add(1, 2); // deduced to be Add(int, int);
 Add(1.5, 2.3); // deduced to be Add(double, double);
 Add(1.5, "Hello"); // compiler error!

 Sub(1.5, 1); // deduced to be Add(double, int);
 Sub(1, 1.1); // deduced to be Add(int, int); compiler error, 
 double can not converted to int automatically
Types can be deduced automatically, so you can simply write: auto Add(A, B)(A a, B b); The type is explicit in the *declaration*, but when you call "add(1, 2)", the compiler will *deduce* A and B to be int. Ditto for sub: auto Sub(A a)(A a, int b);
Thanks for reply! auto Add(A, B)(A a, B b); // Yes, this is the template function declaration of D manner But I mean if the syntax can be more simple? auto Add(A, B)(A a, B b); // type A, B appears twice // Can we just make it more simple? auto Add(a, b) { }
Aug 02 2013
next sibling parent reply "Tommi" <tommitissari hotmail.com> writes:
On Friday, 2 August 2013 at 20:50:00 UTC, SteveGuo wrote:
 auto Add(A, B)(A a, B b); // Yes, this is the template function 
 declaration of D manner

 But I mean if the syntax can be more simple?

 auto Add(A, B)(A a, B b); // type A, B appears twice

 // Can we just make it more simple?
 auto Add(a, b)
 {
 }
I think it could get pretty confusing. I.e.: module foo; struct a { } struct b { } ---- module bar; import foo; auto Add(a, b) { } // [1] ---- [1] Here the unsuspecting programmer thinks he's writing a template function, not knowing that one module he's importing actually specifies 'a' and 'b' as types, which makes his Add a regular function taking unnamed variables of types 'a' and 'b'.
Aug 02 2013
parent reply "SteveGuo" <steveguo outlook.com> writes:
 I think it could get pretty confusing. I.e.:

 module foo;

 struct a { }
 struct b { }

 ----
 module bar;

 import foo;

 auto Add(a, b) { } // [1]

 ----
 [1] Here the unsuspecting programmer thinks he's writing a 
 template function, not knowing that one module he's importing 
 actually specifies 'a' and 'b' as types, which makes his Add a 
 regular function taking unnamed variables of types 'a' and 'b'.
We know that normal function parameter declaration is the form of "PARAMTYPE param" but in this declaration "auto Add(a, b) { }" the parameter do not have PARAMTYPE, compiler can detect this issue, so, the compiler knows a or b is not a type, it treats them as template
Aug 02 2013
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/02/2013 11:20 PM, SteveGuo wrote:
 I think it could get pretty confusing. I.e.:

 module foo;

 struct a { }
 struct b { }

 ----
 module bar;

 import foo;

 auto Add(a, b) { } // [1]

 ----
 [1] Here the unsuspecting programmer thinks he's writing a template
 function, not knowing that one module he's importing actually
 specifies 'a' and 'b' as types, which makes his Add a regular function
 taking unnamed variables of types 'a' and 'b'.
We know that normal function parameter declaration is the form of "PARAMTYPE param" but in this declaration "auto Add(a, b) { }" the parameter do not have PARAMTYPE, compiler can detect this issue, so, the compiler knows a or b is not a type, it treats them as template
Note that currently this is parsed as having _only_ PARAMTYPE.
Aug 02 2013
parent reply "SteveGuo" <steveguo outlook.com> writes:
 Note that currently this is parsed as having _only_ PARAMTYPE.
I just tested _only_ void foo(_only_ a) { } but the compiler complaints "undefined identifier _only_"
Aug 02 2013
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Friday, 2 August 2013 at 21:36:38 UTC, SteveGuo wrote:
 Note that currently this is parsed as having _only_ PARAMTYPE.
I just tested _only_ void foo(_only_ a) { } but the compiler complaints "undefined identifier _only_"
<facepalm /> He meant that when you only have a single token it is parsed as PARAMTYPE and not varname. EG: void foo(int);
Aug 02 2013
parent reply "SteveGuo" <steveguo outlook.com> writes:
 He meant that when you only have a single token it is parsed as 
 PARAMTYPE and not varname.

 EG:

 void foo(int);
Thanks for pointing out my misunderstanding. But we can make a compiler which can "understand" what we want it understand. void foo(int); // this is just a declaration, not a definition auto foo(a) // this is a definition, with a function body, they are different { }
Aug 02 2013
next sibling parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Friday, 2 August 2013 at 22:00:44 UTC, SteveGuo wrote:
 He meant that when you only have a single token it is parsed 
 as PARAMTYPE and not varname.

 EG:

 void foo(int);
Thanks for pointing out my misunderstanding. But we can make a compiler which can "understand" what we want it understand. void foo(int); // this is just a declaration, not a definition auto foo(a) // this is a definition, with a function body, they are different { }
No difference. void foo(int) {} Is perfectly legal.
Aug 02 2013
parent reply "SteveGuo" <steveguo outlook.com> writes:
 void foo(int)
 {}

 Is perfectly legal.
But we can make a compiler which think its illegal.
Aug 02 2013
parent reply "SteveGuo" <steveguo outlook.com> writes:
 void foo(int)
 {}

 Is perfectly legal.
We could change the language definition, make things like "void foo(int) {}" illegal
Aug 02 2013
parent "Dicebot" <public dicebot.lv> writes:
On Friday, 2 August 2013 at 22:12:29 UTC, SteveGuo wrote:
 void foo(int)
 {}

 Is perfectly legal.
We could change the language definition, make things like "void foo(int) {}" illegal
No. Useless breaking change.
Aug 02 2013
prev sibling parent "SteveGuo" <steveguo outlook.com> writes:
void foo(int); // function declaration

void foo(int a) {} // function definition

auto foo(a) {} // template function definition
Aug 02 2013
prev sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Friday, 2 August 2013 at 21:20:55 UTC, SteveGuo wrote:
 We know that normal function parameter declaration is the form 
 of "PARAMTYPE param"
Wrong. Specifying only types was perfectly legal in C and remains so in D. It would have been a major breaking change.
Aug 02 2013
next sibling parent "SteveGuo" <steveguo outlook.com> writes:
 Wrong. Specifying only types was perfectly legal in C and 
 remains so in D. It would have been a major breaking change.
auto Add(a, b) {} Is it feasible? "Specifying only types was perfectly legal in C and emains so in D" Why don't we change our thinking way? Why we couldn't eliminate "PARAMTYPE _only_", make "auto Add(a, b) {} " works?
Aug 02 2013
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2013-08-02 21:30:20 +0000, Dicebot said:

 On Friday, 2 August 2013 at 21:20:55 UTC, SteveGuo wrote:
 We know that normal function parameter declaration is the form of 
 "PARAMTYPE param"
Wrong. Specifying only types was perfectly legal in C and remains so in D. It would have been a major breaking change.
One variant discussed was: auto fun(auto x, auto y) { … } We concluded that's poor style anyway because most function should have constraints on types. Truth be told, at the time of that decision parameter names (viz. x and y) could not be used in template constraints. Now they could, so in a way that reopens the question. Either way, this is not enabling something we couldn't do, so it's not high on the priority list. Andrei
Aug 02 2013
parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 8/2/13, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:
 auto fun(auto x, auto y) { =85 }

 Truth be told, at the time of that decision
 parameter names (viz. x and y) could not be used in template
 constraints. Now they could, so in a way that reopens the question.
You'd still have to use typeof(x) and typeof(y) to extract the types, so even though you end up making the template declaration simpler you also make the constraint more complicated. Anyway after one uses templates for a longer while it becomes apparent that they're rather easy to use in D.
Aug 02 2013
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/03/2013 12:06 AM, Andrej Mitrovic wrote:
 On 8/2/13, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:
 auto fun(auto x, auto y) { … }

 Truth be told, at the time of that decision
 parameter names (viz. x and y) could not be used in template
 constraints. Now they could, so in a way that reopens the question.
You'd still have to use typeof(x) and typeof(y) to extract the types, so even though you end up making the template declaration simpler you also make the constraint more complicated. ...
bool compare(a,b) if(__traits(compiles,a<b)) { return a<b; }
Aug 02 2013
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 8/2/13 3:17 PM, Timon Gehr wrote:
 On 08/03/2013 12:06 AM, Andrej Mitrovic wrote:
 On 8/2/13, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:
 auto fun(auto x, auto y) { … }

 Truth be told, at the time of that decision
 parameter names (viz. x and y) could not be used in template
 constraints. Now they could, so in a way that reopens the question.
You'd still have to use typeof(x) and typeof(y) to extract the types, so even though you end up making the template declaration simpler you also make the constraint more complicated. ...
bool compare(a,b) if(__traits(compiles,a<b)) { return a<b; }
Direct use of __traits is unrecommended outside the stdlib. I had this pattern in mind: bool compare(auto a, auto b) if (is(typeof(a < b) : bool)) { ... } Andrei
Aug 02 2013
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/03/2013 12:19 AM, Andrei Alexandrescu wrote:
 On 8/2/13 3:17 PM, Timon Gehr wrote:
 On 08/03/2013 12:06 AM, Andrej Mitrovic wrote:
 On 8/2/13, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:
 auto fun(auto x, auto y) { … }

 Truth be told, at the time of that decision
 parameter names (viz. x and y) could not be used in template
 constraints. Now they could, so in a way that reopens the question.
You'd still have to use typeof(x) and typeof(y) to extract the types, so even though you end up making the template declaration simpler you also make the constraint more complicated. ...
bool compare(a,b) if(__traits(compiles,a<b)) { return a<b; }
Direct use of __traits is unrecommended outside the stdlib.
The language is not expressive enough to wrap __traits(compiles,a<b) in the stdlib.
 I had this pattern in mind:

 bool compare(auto a, auto b) if (is(typeof(a < b) : bool)) { ... }
 ...
Checking for implicit conversion to bool is redundant due to how operator overloading is handled for '<'. Furthermore, this constraint is not sufficient. bool compare(A,B)(A a,B b) if (is(typeof(a < b) : bool)){ return a<b; } void main(){ int o(T)(T r){ return 0; } static struct S{ alias o opCmp; } compare(S(),S()); // causes error in template body } DMD's implementation of __traits(compiles,...) currently shares this issue; this is a compiler bug as far as I can tell. The above behaviour is to be expected for is(typeof(.)) though.
Aug 02 2013
prev sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Fri, Aug 02, 2013 at 03:19:33PM -0700, Andrei Alexandrescu wrote:
 On 8/2/13 3:17 PM, Timon Gehr wrote:
On 08/03/2013 12:06 AM, Andrej Mitrovic wrote:
On 8/2/13, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:
auto fun(auto x, auto y) { … }

Truth be told, at the time of that decision
parameter names (viz. x and y) could not be used in template
constraints. Now they could, so in a way that reopens the question.
You'd still have to use typeof(x) and typeof(y) to extract the types, so even though you end up making the template declaration simpler you also make the constraint more complicated. ...
bool compare(a,b) if(__traits(compiles,a<b)) { return a<b; }
Direct use of __traits is unrecommended outside the stdlib. I had this pattern in mind: bool compare(auto a, auto b) if (is(typeof(a < b) : bool)) { ... }
[...] I like this syntax. I'm worried, though, about how it will interact with explicit template parameters. E.g., how would you express this: bool func(R,T,U)(T t, U u) { ... } in the new syntax? bool func(R)(auto t, auto u) { ... } ? What if we have variadics on either side? I'm still on the fence as to whether we should add the new syntax, nice as it is. The current syntax is far more unambiguous, and allows you to specify signature constraints on the input types directly, as well as use it in the return type spec, without needing to say typeof(t) or typeof(u). T -- "The whole problem with the world is that fools and fanatics are always so certain of themselves, but wiser people so full of doubts." -- Bertrand Russell. "How come he didn't put 'I think' at the end of it?" -- Anonymous
Aug 02 2013
parent reply "SteveGuo" <steveguo outlook.com> writes:
 I like this syntax.

 I'm worried, though, about how it will interact with explicit 
 template
 parameters. E.g., how would you express this:

 	bool func(R,T,U)(T t, U u) { ... }

 in the new syntax?

 	bool func(R)(auto t, auto u) { ... }

 ?

 What if we have variadics on either side?

 I'm still on the fence as to whether we should add the new 
 syntax, nice
 as it is. The current syntax is far more unambiguous, and 
 allows you to
 specify signature constraints on the input types directly, as 
 well as
 use it in the return type spec, without needing to say 
 typeof(t) or
 typeof(u).


 T
If these syntax is feasible to template functions, is it possible to apply it to class template? class A { int a; // normal member auto b; // template member? }
Aug 02 2013
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sat, Aug 03, 2013 at 01:03:36AM +0200, SteveGuo wrote:
I like this syntax.

I'm worried, though, about how it will interact with explicit
template parameters. E.g., how would you express this:

	bool func(R,T,U)(T t, U u) { ... }

in the new syntax?

	bool func(R)(auto t, auto u) { ... }

?

What if we have variadics on either side?

I'm still on the fence as to whether we should add the new syntax,
nice as it is. The current syntax is far more unambiguous, and allows
you to specify signature constraints on the input types directly, as
well as use it in the return type spec, without needing to say
typeof(t) or typeof(u).


T
If these syntax is feasible to template functions, is it possible to apply it to class template? class A { int a; // normal member auto b; // template member? }
I think that's a bad idea. It's too ambiguous. What will you do with template member functions? class A { auto b(auto c) { ... } } What are the template parameters of A? I still think the current syntax is better. It's a little more verbose in some cases, but I think that's not a big deal. After having used D templates for a while now, the syntax is actually very comfortable to use. I think this kind of cosmetic change is not worth the effort (and potential breakage) at this point in time. T -- A computer doesn't mind if its programs are put to purposes that don't match their names. -- D. Knuth
Aug 02 2013
parent reply "SteveGuo" <steveguo outlook.com> writes:
 	class A
 	{
 		auto b(auto c) { ... }
 	}

 What are the template parameters of A?
class A { void foo(auto x) { ... } } int main() { scope a = new A; a.foo(1); // this means A has a member function "void foo(int x) {...}" a.foo(1.1); // this means A has another member function "void foo(double x) {...}" // compiler will automatically build two versions of function "foo" }
Aug 02 2013
next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sat, Aug 03, 2013 at 01:20:02AM +0200, SteveGuo wrote:
 
	class A
	{
		auto b(auto c) { ... }
	}

What are the template parameters of A?
class A { void foo(auto x) { ... } } int main() { scope a = new A; a.foo(1); // this means A has a member function "void foo(int x) {...}" a.foo(1.1); // this means A has another member function "void foo(double x) {...}" // compiler will automatically build two versions of function "foo" }
How would you translate this to the new syntax: class A(T,U) { T fun1(U x) { ... } U fun2(T x) { ... } V fun3(V)(V x) { ... } auto fun4(T)(T x) { ... } auto fun5(V)(T x, V y) { ... } const(T) fun6(T x) { ... } T p; T q; U r; U s; } ? T -- The easy way is the wrong way, and the hard way is the stupid way. Pick one.
Aug 02 2013
prev sibling next sibling parent "SteveGuo" <steveguo outlook.com> writes:
class A
{
      auto n;

      void foo(auto x) { ... }
}

int main()
{
     scope a = new A;
     scope b = new A;

     a.foo(1); // this means A has a member function "void foo(int
x) {...}"
     a.foo(1.1); // this means A has another member function "void
foo(double x) {...}"
     // compiler will automatically build two versions of function
"foo"

     b.foo("Hello"); // this means A has a third "foo" member 
function with parameter "string []"

     a.n = 1.3; // class A(type 1), which has a data member double 
n;
     b.n = 1 // class A(type 2), which has a data member int n;

     /*
     So there are two class type A1 and A2

     class A1
    {
        double n;

         void foo(int x) { ... }
    }

     class A2
    {
        int n;

         void foo(double x) { ... }
    }

    */

}
Aug 02 2013
prev sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Fri, Aug 02, 2013 at 04:29:39PM -0700, H. S. Teoh wrote:
[...]
 How would you translate this to the new syntax:
 
 	class A(T,U)
 	{
 		T fun1(U x) { ... }
 		U fun2(T x) { ... }
 		V fun3(V)(V x) { ... }
 		auto fun4(T)(T x) { ... }
 		auto fun5(V)(T x, V y) { ... }
 		const(T) fun6(T x) { ... }
 
 		T p;
 		T q;
 		U r;
 		U s;
 	}
[...] Since no good answer is forthcoming, I'm forced to conclude that the new syntax is only marginally useful, and doesn't handle all the cases the current syntax can. So I don't think this change is worth the effort. T -- The computer is only a tool. Unfortunately, so is the user. -- Armaphine, K5
Aug 03 2013
prev sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Friday, 2 August 2013 at 20:50:00 UTC, SteveGuo wrote:
 But I mean if the syntax can be more simple?

 auto Add(A, B)(A a, B b); // type A, B appears twice

 // Can we just make it more simple?
 auto Add(a, b)
 {
 }
Question is "should we"? It creates syntax ambiguity (a and b can be already existing types) and does not really improve language.
Aug 02 2013
parent reply "SteveGuo" <steveguo outlook.com> writes:
 Question is "should we"? It creates syntax ambiguity (a and b 
 can be already existing types) and does not really improve 
 language.
Sorry for my pool English:p I think compiler can detect the difference. auto Add(a, b) {} // Compiler can detect "there is nothing in front of a and b, so a and b is template, not types defined in other modules"
Aug 02 2013
parent "QAston" <qaston gmail.com> writes:
On Friday, 2 August 2013 at 21:29:12 UTC, SteveGuo wrote:
 Question is "should we"? It creates syntax ambiguity (a and b 
 can be already existing types) and does not really improve 
 language.
Sorry for my pool English:p I think compiler can detect the difference. auto Add(a, b) {} // Compiler can detect "there is nothing in front of a and b, so a and b is template, not types defined in other modules"
auto Add(auto a, auto b) would be unambigious imo. I don't see a need for that language change though. My favourite colour of a bikeshed is blue.
Aug 02 2013
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/2/2013 1:34 PM, SteveGuo wrote:
 I'm not an expert on programming language, if I made a naive issue, just
forgive
 me:p
We never forgive, and the internet never forgets! :-)
 Can we declare a template function like this?

 auto Add(a, b) // Note a, b do not have type, that means a and b use template
type
 {
      return a + b;
 }

 auto Sub(a, int b) // a uses template type, b is fixed to int
 {
      return a - b;
 }
The trouble with this is that sometimes people will use a type without an identifier in order to indicate that the parameter is not used: auto Foo(int, unsigned x) But also note that for lambdas, D does allow the form you suggest, as there weren't backwards compatibility issues with it.
Aug 02 2013
parent "SteveGuo" <steveguo outlook.com> writes:
 The trouble with this is that sometimes people will use a type 
 without an identifier in order to indicate that the parameter 
 is not used:

 auto Foo(int, unsigned x)

 But also note that for lambdas, D does allow the form you 
 suggest, as there weren't backwards compatibility issues with 
 it.
I know there is no perfect things in the world, But I hope that D can approach the perfect, Because I really love this language! Thanks for inventing this beautiful language:)
Aug 02 2013
prev sibling next sibling parent reply "F i L" <witte2008 gmail.com> writes:
I've brought this up on here awhile ago, and many people seemed 
to be against it. Which I don't agree with, since the ambiguities 
it creates are easily addressed (from a design perspective at 
least) and only exist so that C-style code is usable within D. It 
could work like:

    auto func(a, b)     // auto func(A, B)(A a, B b)
    auto func(int a, b) // auto func(B)(int a, B b)
    auto func(int ?)    // C-style: auto func(int)

Or...

    auto func(auto a, auto b) // like C++14

I mean honestly, who's hand-writing a bunch of functions with 
nameless params in real D code? Sure it's used for linking to C, 
which is semi-common, but I think having the much cleaner syntax 
available to "actual" D code makes more sense that not having it 
solely for linking-to-C-in-familiar-C-style reasons.
Aug 02 2013
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2013-08-03 00:51:19 +0000, F i L said:

 I've brought this up on here awhile ago, and many people seemed to be 
 against it. Which I don't agree with, since the ambiguities it creates 
 are easily addressed (from a design perspective at least) and only 
 exist so that C-style code is usable within D. It could work like:
 
     auto func(a, b)     // auto func(A, B)(A a, B b)
     auto func(int a, b) // auto func(B)(int a, B b)
     auto func(int ?)    // C-style: auto func(int)
 
 Or...
 
     auto func(auto a, auto b) // like C++14
 
 I mean honestly, who's hand-writing a bunch of functions with nameless 
 params in real D code? Sure it's used for linking to C, which is 
 semi-common, but I think having the much cleaner syntax available to 
 "actual" D code makes more sense that not having it solely for 
 linking-to-C-in-familiar-C-style reasons.
The converse question is who's hand-writing a bunch of functions that don't need their arguments' types in any way (for constraints or otherwise). There are very few functions that really apply to all types. It's possible that by allowing auto parameter types we encourage a sloppy style. Andrei
Aug 02 2013
parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Saturday, 3 August 2013 at 01:15:48 UTC, Andrei Alexandrescu 
wrote:
 On 2013-08-03 00:51:19 +0000, F i L said:

 I've brought this up on here awhile ago, and many people 
 seemed to be against it. Which I don't agree with, since the 
 ambiguities it creates are easily addressed (from a design 
 perspective at least) and only exist so that C-style code is 
 usable within D. It could work like:
 
    auto func(a, b)     // auto func(A, B)(A a, B b)
    auto func(int a, b) // auto func(B)(int a, B b)
    auto func(int ?)    // C-style: auto func(int)
 
 Or...
 
    auto func(auto a, auto b) // like C++14
 
 I mean honestly, who's hand-writing a bunch of functions with 
 nameless params in real D code? Sure it's used for linking to 
 C, which is semi-common, but I think having the much cleaner 
 syntax available to "actual" D code makes more sense that not 
 having it solely for linking-to-C-in-familiar-C-style reasons.
The converse question is who's hand-writing a bunch of functions that don't need their arguments' types in any way (for constraints or otherwise). There are very few functions that really apply to all types. It's possible that by allowing auto parameter types we encourage a sloppy style. Andrei
The existence of template restrictions and the swathes of different things in std.traits and elsewhere really persuaded me to think about the requirements of my templates. Having to spell it out a bit is a good thing. In short: I agree.
Aug 03 2013
prev sibling next sibling parent "Suliman" <evermind live.ru> writes:
 I've brought this up on here awhile ago, and many people seemed 
 to be against it. Which I don't agree with, since the 
 ambiguities it creates are easily addressed (from a design 
 perspective at least) and only exist so that C-style code is 
 usable within D. It could work like:

    auto func(a, b)     // auto func(A, B)(A a, B b)
    auto func(int a, b) // auto func(B)(int a, B b)
    auto func(int ?)    // C-style: auto func(int)
I like it!
Aug 02 2013
prev sibling parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Saturday, 3 August 2013 at 00:51:21 UTC, F i L wrote:
 I've brought this up on here awhile ago, and many people seemed 
 to be against it. Which I don't agree with, since the 
 ambiguities it creates are easily addressed (from a design 
 perspective at least) and only exist so that C-style code is 
 usable within D. It could work like:

    auto func(a, b)     // auto func(A, B)(A a, B b)
    auto func(int a, b) // auto func(B)(int a, B b)
    auto func(int ?)    // C-style: auto func(int)
Regardless of the existing merits, that would be a (massive) breaking change, and as mentioned, it brings nothing we couldn't do before...
 Or...

    auto func(auto a, auto b) // like C++14

 I mean honestly, who's hand-writing a bunch of functions with 
 nameless params in real D code? Sure it's used for linking to 
 C, which is semi-common, but I think having the much cleaner 
 syntax available to "actual" D code makes more sense that not 
 having it solely for linking-to-C-in-familiar-C-style reasons.
Anytime I write the body of a function that doesn't use one of its args, I keep the arg name empty. This implicitly documents that the arg is unused. Many people do this in C++ too, since msvc will flag you for not doing it anyways. So your answer your question: "who's hand-writing a bunch of functions with nameless params in real D code": Lot's of people, including in Phobos.
Aug 03 2013
parent reply "F i L" <witte2008 gmail.com> writes:
monarch_dodra wrote:
 Regardless of the existing merits, that would be a (massive) 
 breaking change, and as mentioned, it brings nothing we 
 couldn't do before...
Sure, but not if you do it like my second example: auto func(auto a, auto b) // like C++14 That doesn't break anything, right?
 Anytime I write the body of a function that doesn't use one of 
 its args, I keep the  arg name empty. This implicitly documents 
 that the arg is unused. Many people do this in C++ too, since 
 msvc will flag you for not doing it anyways. So your answer 
 your question: "who's hand-writing a bunch of functions with  
 nameless params in real D code": Lot's of people, including in 
 Phobos.
Fair enough. However, using 'auto' like above would allow cleaner syntax without getting in your way I think.
Aug 03 2013
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Saturday, 3 August 2013 at 08:59:41 UTC, F i L wrote:
 monarch_dodra wrote:
 Regardless of the existing merits, that would be a (massive) 
 breaking change, and as mentioned, it brings nothing we 
 couldn't do before...
Sure, but not if you do it like my second example: auto func(auto a, auto b) // like C++14 That doesn't break anything, right?
I'm not sure auto is the best choice of keywords, given potential clashes with auto ref: What if you want to pass a by ref? auto func(auto ref a, auto ref b) ? auto func(ref auto a, ref auto b) ? What if you want to pass them by *auto* ref? auto func(auto auto ref a, auto auto ref b) ? auto func(auto ref auto a, auto ref auto b) ? At this point, I'd really prefer just seeing classic template syntax...
Aug 03 2013
parent "F i L" <witte2008 gmail.com> writes:
monarch_dodra wrote:
 I'm not sure auto is the best choice of keywords, given 
 potential clashes with auto ref:

 What if you want to pass a by ref?
 auto func(auto ref a, auto ref b) ?
 auto func(ref auto a, ref auto b) ?
 
 What if you want to pass them by *auto* ref?
 auto func(auto auto ref a, auto auto ref b) ?
 auto func(auto ref auto a, auto ref auto b) ?

 At this point, I'd really prefer just seeing classic template 
 syntax...
Okay, so I mostly agree with this. I guess adding this change would mostly likely require a breaking change elsewhere, and I can see the merits of not doing anything like that for good while. Thanks for being so convincing.
Aug 03 2013
prev sibling parent "Flamaros" <flamaros.xavier gmail.com> writes:
On Friday, 2 August 2013 at 20:34:04 UTC, SteveGuo wrote:
 I'm not an expert on programming language, if I made a naive 
 issue, just forgive me:p

 Can we declare a template function like this?

 auto Add(a, b) // Note a, b do not have type, that means a and 
 b use template type
 {
     return a + b;
 }

 auto Sub(a, int b) // a uses template type, b is fixed to int
 {
     return a - b;
 }

 When we call the function,

 Add(1, 2); // deduced to be Add(int, int);
 Add(1.5, 2.3); // deduced to be Add(double, double);
 Add(1.5, "Hello"); // compiler error!

 Sub(1.5, 1); // deduced to be Add(double, int);
 Sub(1, 1.1); // deduced to be Add(int, int); compiler error, 
 double can not converted to int automatically
I prefer the current template syntax, it's nice to want to reduce the number of keywords/syntax, but generally to understand the code it's better for productivity to have something really explicit. When you read an old code or something written by someone else it's really important to see at the first sight what the code is intended to do. auto keyword hide too much how variables are used, is it ref? const?,...
Aug 03 2013