www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - "cannot deduce function from argument types" issue.

reply ted <foo bar.com> writes:
Hi!

I get the following compile error (linux, dmd2.066.1):
test.d(13): Error: template test.testFunc cannot deduce function from 
argument types !()(double[], double), candidates are:
test.d(3):        test.testFunc(R)(R range, ElementType!R foo)


For the following test file:
import std.range: ElementType, isInputRange;

ElementType!R testFunc(R)( R range, ElementType!R foo)	// compiles with 
double foo
{
    static assert( isInputRange!R );
    ElementType!R retVal = foo*foo;
    return retVal;                                                             
                                                                               
                                                                               
   
}                                                                              
                                                                               
                                                                               
   
                                                                               
                                                                               
                                                                               
   
void main()                                                                    
                                                                               
                                                                               
   
{                                                                              
                                                                               
                                                                               
   
    double[] values = [0.0, 3.0, -1.0, 5.0];                                   
                                                                               
                                                                               
   
    auto result = testFunc( values, 8.8 );                                     
                                                                               
                                                                               
   
}

And I'm not sure what I'm doing incorrectly. It compiles/works fine if I 
hardcode the type for foo.
Could someone enlighten me ?

regards,
ted
Feb 10 2015
next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 02/10/2015 12:31 AM, ted wrote:

 ElementType!R testFunc(R)( R range, ElementType!R foo)	// compiles with
 double foo
If think it is a little too much to ask from the template system of D. A proper way of doing the same thing is to use a template constraint: ElementType!R testFunc(R, E)( R range, E foo) if (is (E : ElementType!R)) Ali
Feb 10 2015
next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Ali Çehreli:

 If think it is a little too much to ask from the template 
 system of D.
I remember hitting a similar problem with code like this bar() function: // OK void foo(size_t N1, size_t N2)(int[N1] a, int[N2] b) if (N2 == N1 ^^ 2) {} // Not OK void bar(size_t N)(int[N] a, int[N ^ 2] b) {} void main() { int[2] a = [1, 2]; int[4] b = [1, 2, 3, 4]; foo(a, b); bar(a, b); } So perhaps my suggestion to file an enhancement request is not a good idea... Bye, bearophile
Feb 10 2015
next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
 void bar(size_t N)(int[N] a, int[N ^ 2] b) {}
I meant: void bar(size_t N)(int[N] a, int[N ^^ 2] b) {}
Feb 10 2015
prev sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 02/10/2015 01:08 AM, bearophile wrote:

 // Not OK
 void bar(size_t N)(int[N] a, int[N ^^ 2] b) {}
 So perhaps my suggestion to file an enhancement request is not
 a good idea...
I am not sure. Although the template system already does pretty clever deductions, I think they are all based on hints given by the programmer. They work "forward" from the rules. However, both in your example above and in ted's code, the compiler has to solve a problem similar to declarative programming languages to arrive at the intent. For example, it must apply sqrt to the second length to figure out N. Admittedly, it is not apparent in the code above because the first parameter is already trivially N so the human reader thinks "N comes from the first argument and it must also satisfy the second argument". The following would ask the compiler to work backward from the argument: void bar(size_t N)(int[N ^^ 2] b) {} "Take a value from the argument, take its square root and then use that value to figure out the instantiation value of this template." Ali
Feb 10 2015
prev sibling parent ted <foo bar.com> writes:
Ali Çehreli wrote:

 On 02/10/2015 12:31 AM, ted wrote:
 
  > ElementType!R testFunc(R)( R range, ElementType!R foo)	// 
compiles
  > with double foo
 
 If think it is a little too much to ask from the template system of D. A
 proper way of doing the same thing is to use a template constraint:
 
 ElementType!R testFunc(R, E)( R range, E foo)
      if (is (E : ElementType!R))
 
 Ali
....thanks !
Feb 10 2015
prev sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
ted:

 Could someone enlighten me ?
This works: import std.range: ElementType, isInputRange; ElementType!R testFunc(R, T)(R range, T foo) if (is(ElementType!R == T)) { static assert(isInputRange!R); typeof(return) retVal = foo ^^ 2; // More DRY. return retVal; } void main() { auto values = [0.0, 3.0, -1.0, 5.0]; auto result = testFunc(values, 8.8); } The D compiler seems unable to compute ElementType!R in the function signature. If I am right, then this seems worth an enhancement request. Bye, bearophile
Feb 10 2015
parent reply ted <foo bar.com> writes:
bearophile wrote:

 ted:
 
 Could someone enlighten me ?
This works: import std.range: ElementType, isInputRange; ElementType!R testFunc(R, T)(R range, T foo) if (is(ElementType!R == T)) { static assert(isInputRange!R); typeof(return) retVal = foo ^^ 2; // More DRY. return retVal; } void main() { auto values = [0.0, 3.0, -1.0, 5.0]; auto result = testFunc(values, 8.8); } The D compiler seems unable to compute ElementType!R in the function signature. If I am right, then this seems worth an enhancement request. Bye, bearophile
thanks !... ... where you say 'More DRY' above, are you referring to - foo^^2 ( I just did foo*foo for the sake of the example), or - typeof(return) - a construct I am completely unfamiliar with and will now have to look up ! If it is 'typeof(return)' why would this be selected over ElementType!R ?? Is it more idiomatic ? regards, ted
Feb 10 2015
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
ted:

 ... where you say 'More DRY' above, are you referring to
I was referring to both, but mostly to the typeof. It's more DRY (http://en.wikipedia.org/wiki/Don%27t_repeat_yourself ). You are stating only once the type of the return variable. This is less bug-prone. Bye, bearophile
Feb 10 2015
parent ted <foo bar.com> writes:
bearophile wrote:

 ted:
 
 ... where you say 'More DRY' above, are you referring to
I was referring to both, but mostly to the typeof. It's more DRY (http://en.wikipedia.org/wiki/Don%27t_repeat_yourself ). You are stating only once the type of the return variable. This is less bug-prone. Bye, bearophile
Ha ! ..more stuff to learn! many thanks... regards, ted
Feb 10 2015