www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Why does sum not work in static arrays?

reply mw <mingwu gmail.com> writes:
cross-post here for general discussion about the library & 
language.

https://forum.dlang.org/post/naaxgyuzahnhjltblbtp forum.dlang.org

On Sunday, 6 December 2015 at 12:27:49 UTC, cym13 wrote:
 On Sunday, 6 December 2015 at 12:23:05 UTC, Tim K. wrote:
 Hi! I have the following code:

     int main(string[] argv)
     {
         import std.algorithm: sum;
         import std.stdio: writeln;

         uint[3] a1 = [1, 2, 3];
         uint[] a2;
         for (int i = 1; i <= 3; ++i)
             a2 ~= i;

         writeln("a1: ", sum(a1));
         writeln("a2: ", sum(a2));
         return 0;
     }

 This throws the error:
 dummy.d(11): Error: template std.algorithm.iteration.sum 
 cannot deduce function from argument types !()(uint[3]), 
 candidates are:
 /usr/include/dmd/phobos/std/algorithm/iteration.d(3916):
  std.algorithm.iteration.sum(R)(R r) if (isInputRange!R && 
 !isInfinite!R && is(typeof(r.front + r.front)))
 /usr/include/dmd/phobos/std/algorithm/iteration.d(3927):
  std.algorithm.iteration.sum(R, E)(R r, E seed) if 
 (isInputRange!R && !isInfinite!R && is(typeof(seed = seed + 
 r.front)))


 So a dynamic array works just fine. In fact, if I uncomment 
 the line in question the program compiles and outputs the 
 correct value (for a2). Why does "sum" not work on static 
 arrays?


 Regards
So that you do not shoot yourself in the foot too easily. A static array is a value type so it is passed by value to functions. If you pass a 1M array to a function... well, I guesse you don't want to do that.
Can the template func `sum()` be made to take `ref` of a static array?
 The solution is to slice it:   a1[].sum;   That way you avoid 
 the problem.
While I understand the explanation of the current behavior, and the work-around, this inconstancy of making func calls means either the library, or the language leaves something to be desired: i.e dynamic array and static array cannot be used interchangeably: (sure I'm not talking about array decl / allocation, the user have to take different actions) I'm talking about a simple function call to calc the sum of the array. ``` sum(static_array[]); // v.s. sum(dynamic_array); ``` For example, if the user first decl a static array for fast prototyping, and later changed mind to use dynamic array, then s/he need to change the call all over the places. (I hope you are not telling me, every time people should use: ``` array_func(any_array[]); ``` is the correct D-idiom to use array in a func call)
Oct 10 2020
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 10/10/20 3:10 PM, mw wrote:
 cross-post here for general discussion about the library & language.
 
 https://forum.dlang.org/post/naaxgyuzahnhjltblbtp forum.dlang.org
 
 On Sunday, 6 December 2015 at 12:27:49 UTC, cym13 wrote:
 On Sunday, 6 December 2015 at 12:23:05 UTC, Tim K. wrote:
 Hi! I have the following code:

     int main(string[] argv)
     {
         import std.algorithm: sum;
         import std.stdio: writeln;

         uint[3] a1 = [1, 2, 3];
         uint[] a2;
         for (int i = 1; i <= 3; ++i)
             a2 ~= i;

         writeln("a1: ", sum(a1));
         writeln("a2: ", sum(a2));
         return 0;
     }

 This throws the error:
 dummy.d(11): Error: template std.algorithm.iteration.sum cannot 
 deduce function from argument types !()(uint[3]), candidates are:
 /usr/include/dmd/phobos/std/algorithm/iteration.d(3916):
  std.algorithm.iteration.sum(R)(R r) if (isInputRange!R && 
 !isInfinite!R && is(typeof(r.front + r.front)))
 /usr/include/dmd/phobos/std/algorithm/iteration.d(3927):
  std.algorithm.iteration.sum(R, E)(R r, E seed) if (isInputRange!R && 
 !isInfinite!R && is(typeof(seed = seed + r.front)))


 So a dynamic array works just fine. In fact, if I uncomment the line 
 in question the program compiles and outputs the correct value (for 
 a2). Why does "sum" not work on static arrays?


 Regards
So that you do not shoot yourself in the foot too easily. A static array is a value type so it is passed by value to functions. If you pass a 1M array to a function... well, I guesse you don't want to do that.
Can the template func `sum()` be made to take `ref` of a static array?
There are some functions that deal with static arrays as well as ranges. I would say no to this request though. If you want a range from a static array, use a slice operation. The places which normally deal with ranges should not automatically use static arrays. We are paying the price for this in lifetime bugs.
 dynamic array and static array cannot be used interchangeably: (sure I'm 
 not talking about array decl / allocation, the user have to take 
 different actions) I'm talking about a simple function call to calc the 
 sum of the array.
 ```
    sum(static_array[]);   // v.s.
    sum(dynamic_array);
 ```
 
 For example, if the user first decl a static array for fast prototyping, 
 and later changed mind to use dynamic array, then s/he need to change 
 the call all over the places.
All correct statements. Static arrays are not the same as dynamic arrays.
 
 
 (I hope you are not telling me, every time people should use:
 ```
    array_func(any_array[]);
 ```
 is the correct D-idiom to use array in a func call)
 
No, sum accepts a range. A static array is not a range. Simple as that. Just use a slice operator if you want a range from it. It's no different from any other type that is not a range. For example a std.container.Array is not a range. If you slice it, it gives you a range, which you can then use in algorithms. -Steve
Oct 10 2020