www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Return type deduction

reply Andrea Fontana <nospam example.com> writes:
I asked this some time (years?) ago. Time for a second try :)

Consider this:

---

T simple(T)() { return T.init; }


void main()
{
	int test = simple!int(); // it compiles
	int test2 = simple();    // it doesn't
}

---

Is there any chance to implement this kind of deduction?
Please notice that it doesn't break any existing code, I guess.

For example using my json wrapper [1] this sounds a bit pedantic:

----
user.name = json.get!string("info/name");
user.age  = json.get!int("info/age");
----

If return type deduction could be implemented it would be:

----
user.name = json.get("info/name");
user.age  = json.get("info/age");
----

[1] https://code.dlang.org/packages/jsonwrap

Andrea
Sep 05 2016
next sibling parent reply Daniel Kozak via Digitalmars-d <digitalmars-d puremagic.com> writes:
Dne 5.9.2016 v 11:59 Andrea Fontana via Digitalmars-d napsal(a):

 I asked this some time (years?) ago. Time for a second try :)

 Consider this:

 ---

 T simple(T)() { return T.init; }


 void main()
 {
     int test = simple!int(); // it compiles
     int test2 = simple();    // it doesn't
 }

 ---

 Is there any chance to implement this kind of deduction?
 Please notice that it doesn't break any existing code, I guess.
 ...
 Andrea
AFAIK this is impossible
Sep 05 2016
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 05.09.2016 12:25, Daniel Kozak via Digitalmars-d wrote:
 Dne 5.9.2016 v 11:59 Andrea Fontana via Digitalmars-d napsal(a):

 I asked this some time (years?) ago. Time for a second try :)

 Consider this:

 ---

 T simple(T)() { return T.init; }


 void main()
 {
     int test = simple!int(); // it compiles
     int test2 = simple();    // it doesn't
 }

 ---

 Is there any chance to implement this kind of deduction?
 Please notice that it doesn't break any existing code, I guess.
 ...
 Andrea
AFAIK this is impossible
It's a feature request. (Lambdas also do type deduction based on expected type, now just do the same during IFTI, as a fallback in case not enough information can be deduced from the arguments alone.)
Sep 05 2016
prev sibling next sibling parent reply Lodovico Giaretta <lodovico giaretart.net> writes:
On Monday, 5 September 2016 at 09:59:16 UTC, Andrea Fontana wrote:
 I asked this some time (years?) ago. Time for a second try :)

 Consider this:

 ---

 T simple(T)() { return T.init; }


 void main()
 {
 	int test = simple!int(); // it compiles
 	int test2 = simple();    // it doesn't
 }

 ---

 Is there any chance to implement this kind of deduction?
 Please notice that it doesn't break any existing code, I guess.

 For example using my json wrapper [1] this sounds a bit 
 pedantic:

 ----
 user.name = json.get!string("info/name");
 user.age  = json.get!int("info/age");
 ----

 If return type deduction could be implemented it would be:

 ----
 user.name = json.get("info/name");
 user.age  = json.get("info/age");
 ----

 [1] https://code.dlang.org/packages/jsonwrap

 Andrea
I see just one problem in this request: =========================== T get(T = int)() { return T.init; } double val = get(); // should this call get!double or try to call get!int and give an error? =========================== That is, what takes precedence? Default argument or inference from the destination type? I'd personally prefer this to give an error, as it is ambiguous and error prone.
Sep 05 2016
parent Andrea Fontana <nospam example.com> writes:
On Monday, 5 September 2016 at 11:51:23 UTC, Lodovico Giaretta 
wrote:
 I see just one problem in this request:

 ===========================
 T get(T = int)()
 {
     return T.init;
 }

 double val = get(); // should this call get!double or try to 
 call get!int and give an error?
 ===========================

 That is, what takes precedence? Default argument or inference 
 from the destination type? I'd personally prefer this to give 
 an error, as it is ambiguous and error prone.
I think it should be get!int(). It seems logical and it doesn't break existing code.
Sep 05 2016
prev sibling next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Monday, 5 September 2016 at 09:59:16 UTC, Andrea Fontana wrote:
 I asked this some time (years?) ago. Time for a second try :)
Return type deduction probably won't work, but implicit casts of a custom data type could do this - that's how C++ would do it. Alas, D does not have an implicit cast operator :( best we have is `alias this` but it only allows one right now (despite the book saying it is supposed to do multiple.. and there are some PRs about it). They wouldn't be templated but json could just do a few implicit casts.
Sep 05 2016
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 05.09.2016 14:31, Adam D. Ruppe wrote:
 On Monday, 5 September 2016 at 09:59:16 UTC, Andrea Fontana wrote:
 I asked this some time (years?) ago. Time for a second try :)
Return type deduction probably won't work,
Why? It seems rather easy to do.
 but implicit casts of a
 custom data type could do this - that's how C++ would do it.
 ...
That does not solve the problem that nicely: if no different type is specified the dummy object with the opImplicitCast can be assigned to a variable: auto x = a.get(); // oops This shouldn't compile.
 Alas, D does not have an implicit cast operator :( best we have is
 `alias this` but it only allows one right now (despite the book saying
 it is supposed to do multiple.. and there are some PRs about it). They
 wouldn't be templated but json could just do a few implicit casts.
Sep 05 2016
prev sibling next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 9/5/2016 2:59 AM, Andrea Fontana wrote:
 Is there any chance to implement this kind of deduction?
No. Types are resolved bottom-up, not top-down. Trying to do both may not even be doable in the general case, it certainly makes for all kinds of complexity. It makes a soup out of overload resolution, for example.
Sep 05 2016
prev sibling next sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 9/5/16 5:59 AM, Andrea Fontana wrote:
 I asked this some time (years?) ago. Time for a second try :)

 Consider this:

 ---

 T simple(T)() { return T.init; }


 void main()
 {
     int test = simple!int(); // it compiles
     int test2 = simple();    // it doesn't
auto test3 = simple!int(); Granted, you are still typing "auto", but only specify the type once. -Steve
Sep 06 2016
parent reply Andrea Fontana <nospam example.com> writes:
On Tuesday, 6 September 2016 at 14:21:26 UTC, Steven 
Schveighoffer wrote:
 On 9/5/16 5:59 AM, Andrea Fontana wrote:
 I asked this some time (years?) ago. Time for a second try :)

 Consider this:

 ---

 T simple(T)() { return T.init; }


 void main()
 {
     int test = simple!int(); // it compiles
     int test2 = simple();    // it doesn't
auto test3 = simple!int(); Granted, you are still typing "auto", but only specify the type once. -Steve
Only for the simple case. It would interesting if it would work for: struct Blah { string name; } Blah b; b.name = simple(); or: void myFunc(string s) { ... } myFunc(simple()); Andrea
Sep 07 2016
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 9/7/16 3:19 AM, Andrea Fontana wrote:
 On Tuesday, 6 September 2016 at 14:21:26 UTC, Steven Schveighoffer wrote:
 On 9/5/16 5:59 AM, Andrea Fontana wrote:
 I asked this some time (years?) ago. Time for a second try :)

 Consider this:

 ---

 T simple(T)() { return T.init; }


 void main()
 {
     int test = simple!int(); // it compiles
     int test2 = simple();    // it doesn't
auto test3 = simple!int(); Granted, you are still typing "auto", but only specify the type once. -Steve
Only for the simple case. It would interesting if it would work for: struct Blah { string name; } Blah b; b.name = simple(); or: void myFunc(string s) { ... } myFunc(simple());
Right, but there is a problem here. The connection of the simple return type to the simple template parameter is not necessarily guaranteed. That is, there is no guarantee simple!int is going to return int (for any template). This means the compiler has to determine how to make simple return an int, and this isn't always obvious, or easy to determine. You can, of course, rewrite simple to take advantage of IFTI: void simple(T)(ref T setThis) { setThis = T.init; } simple(b.name); I'd call it initialize, and do it this way: b.name.initialize(); -Steve
Sep 08 2016
parent Andrea Fontana <nospam example.com> writes:
On Thursday, 8 September 2016 at 13:28:15 UTC, Steven 
Schveighoffer wrote:
 Right, but there is a problem here. The connection of the 
 simple return type to the simple template parameter is not 
 necessarily guaranteed. That is, there is no guarantee 
 simple!int is going to return int (for any template).

 This means the compiler has to determine how to make simple 
 return an int, and this isn't always obvious, or easy to 
 determine.
I don't know how compiler works, but my logic was: - I have T simple(T) { ... } - return type == template argument - int ... = simple() => T == int => simple!int I undestand that if it was: auto simple(T) { ... } it should be difficult Probably I'm missing someting about compiler internal structure, not my field. Andrea
Sep 08 2016
prev sibling next sibling parent Rory McGuire via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Mon, Sep 5, 2016 at 11:59 AM, Andrea Fontana via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 I asked this some time (years?) ago. Time for a second try :)

 Consider this:

 ---

 T simple(T)() { return T.init; }


 void main()
 {
         int test = simple!int(); // it compiles
         int test2 = simple();    // it doesn't
 }

 ---

 Is there any chance to implement this kind of deduction?
 Please notice that it doesn't break any existing code, I guess.

 For example using my json wrapper [1] this sounds a bit pedantic:

 ----
 user.name = json.get!string("info/name");
 user.age  = json.get!int("info/age");
 ----

 If return type deduction could be implemented it would be:

 ----
 user.name = json.get("info/name");
 user.age  = json.get("info/age");
 ----

 [1] https://code.dlang.org/packages/jsonwrap

 Andrea
user.name = json.get!(info.name); or user.name = json!(info.name); possible right now. No language changes. Shorter. No strings. compile time type verification. limitation: can't do runtime loading of unknown json structure (but then neither does your proposal). R
Sep 07 2016
prev sibling parent Patric <patric.dexheimer gmail.com> writes:
On Monday, 5 September 2016 at 09:59:16 UTC, Andrea Fontana wrote:
 I asked this some time (years?) ago. Time for a second try :)

 Consider this:

 ---

 T simple(T)() { return T.init; }


 void main()
 {
 	int test = simple!int(); // it compiles
 	int test2 = simple();    // it doesn't
 }

 ---

 Is there any chance to implement this kind of deduction?
 Please notice that it doesn't break any existing code, I guess.

 For example using my json wrapper [1] this sounds a bit 
 pedantic:

 ----
 user.name = json.get!string("info/name");
 user.age  = json.get!int("info/age");
 ----

 If return type deduction could be implemented it would be:

 ----
 user.name = json.get("info/name");
 user.age  = json.get("info/age");
 ----

 [1] https://code.dlang.org/packages/jsonwrap

 Andrea
(I thought that i have see your idea in another lang, but maybe i´m wrong) You can use ref, if you want to simplify your code; void simple(T)( ref T t) { t = T.init; } so maybe your example of the json can be something like this: json.set(user.name,"info/name"); Or with some more little tricks: alias json_set = json.set; user.name.json_set("info/name");
Sep 08 2016