Thread overview
Using "reduce" with user types
Feb 07, 2015
Kadir Erdem Demir
Feb 07, 2015
Rikki Cattermole
Feb 07, 2015
Kadir Erdem Demir
Feb 07, 2015
Meta
Feb 07, 2015
FG
February 07, 2015
I can use filter algorithm with my types easily.

struct A
{
	string value;
	int count;
}


void main(  string[] args )
{
	A[] aArr;
	aArr  ~= A("HTTP", 3);
	aArr  ~= A("HTTPS", 2);
	aArr  ~= A("UNKNOWN_TCP", 4);
	aArr.filter!( a => a.count == 2);

But I couldn't compile when I want to use reduce algorithm. I simply want to get the sum of "count" variables inside of A[]. 	

	auto sum = aArr.reduce!((a,b) => a.count + b.count);

The line above gives

C:\D\dmd2\windows\bin\..\..\src\phobos\std\algorithm.d(770): Error: cannot implicitly convert expression (__lambda3(result, front(_param_1))) of type int to A
C:\D\dmd2\windows\bin\..\..\src\phobos\std\algorithm.d(791): Error: template instance app.main.reduce!((a, b) => a.count + b.count).reduce!(A, A[]) error instantiating
source\app.d(363):        instantiated from here: reduce!(A[])

How can I achieve summing count variables inside A[]?

Best Regards
Kadir Erdem Demir

Ps: The problem caused by my lack of D basics I admit, the reason I can't look up references more  before ask question I am in a bit tight schedule. Sorry for my dummy questions.
February 07, 2015
On 8/02/2015 1:47 a.m., Kadir Erdem Demir wrote:
> I can use filter algorithm with my types easily.
>
> struct A
> {
>      string value;
>      int count;
> }
>
>
> void main(  string[] args )
> {
>      A[] aArr;
>      aArr  ~= A("HTTP", 3);
>      aArr  ~= A("HTTPS", 2);
>      aArr  ~= A("UNKNOWN_TCP", 4);
>      aArr.filter!( a => a.count == 2);
>
> But I couldn't compile when I want to use reduce algorithm. I simply
> want to get the sum of "count" variables inside of A[].
>
>      auto sum = aArr.reduce!((a,b) => a.count + b.count);
>
> The line above gives
>
> C:\D\dmd2\windows\bin\..\..\src\phobos\std\algorithm.d(770): Error:
> cannot implicitly convert expression (__lambda3(result,
> front(_param_1))) of type int to A
> C:\D\dmd2\windows\bin\..\..\src\phobos\std\algorithm.d(791): Error:
> template instance app.main.reduce!((a, b) => a.count +
> b.count).reduce!(A, A[]) error instantiating
> source\app.d(363):        instantiated from here: reduce!(A[])
>
> How can I achieve summing count variables inside A[]?
>
> Best Regards
> Kadir Erdem Demir
>
> Ps: The problem caused by my lack of D basics I admit, the reason I
> can't look up references more  before ask question I am in a bit tight
> schedule. Sorry for my dummy questions.

auto sum = aArr.map!`a.count`.reduce!((a,b) => a + b);

Not much difference.
I tried sum instead of reduce, but it didn't work. Wouldn't matter much as it is the same thing pretty much anyway.
February 07, 2015
> auto sum = aArr.map!`a.count`.reduce!((a,b) => a + b);

Rikki Thanks a lot. It works.

Function map!"a.count"(aArr) surprises me a little.
Because when I read std.algorithm reference: `Implements the homonym function (also known as transform)`.

Which reminds me C++ transform and it will never used for returning a element of the struct.  I expect transform to modify the elements of the range but in D it seem to me it also used traversing the elements.

How can I imagine what "map" does in my mind, because it doesn't matches with the transform concept in my mind?

Regards
Kadir Erdem
February 07, 2015
On 2015-02-07 at 13:47, Kadir Erdem Demir wrote:
>
>      auto sum = aArr.reduce!((a,b) => a.count + b.count);
>
> The line above gives
>
> C:\D\dmd2\windows\bin\..\..\src\phobos\std\algorithm.d(770): Error: cannot implicitly convert expression (__lambda3(result, front(_param_1))) of type int to A
> C:\D\dmd2\windows\bin\..\..\src\phobos\std\algorithm.d(791): Error: template instance app.main.reduce!((a, b) => a.count + b.count).reduce!(A, A[]) error instantiating
> source\app.d(363):        instantiated from here: reduce!(A[])


    // auto sum = aArr.reduce!((a,b) => a.count + b.count); // Wrong

    auto sum = reduce!((a, b) => a + b.count)(0, aArr);     // Good


See here: http://dlang.org/phobos/std_algorithm.html#.reduce
February 07, 2015
On Saturday, 7 February 2015 at 13:38:00 UTC, Kadir Erdem Demir wrote:
> How can I imagine what "map" does in my mind, because it doesn't matches with the transform concept in my mind?

You can think of map as taking a range of something (in this case, an array of A), and calling a user-supplied function on each element in that range. The user-supplied function is a function that describes how to "map" each value in the range to a result. In your case, the function defines how to map from an A to its `count` member variable (it is a function of type A->int).

All "aArr.map!`a.count`" means is that for each A in aArr, return its `count` member. map!`a.count` is some syntax sugar D has to make function calls shorter; It expands to the following:

aArr.map!((A a) {
    return a.count;
})

The main difference between `map` in D and `transform` in C++ is, I believe, twofold. First off, `transform` is eager, meaning it does as much work as possible as son as possible. On the other hand, `map` does as little work as possible as late as possible. For the following code:

iota(10).map!(n => writeln(n)).take(5).array

Only "0 1 2 3 4" will be printed, as map is lazy and will not do work it doesn't have to.

Second of all, map returns a range that is the result of applying the supplied function to each element of aArr. C++'s tranform copies the result to another user-supplied range. If you wanted the equivalent of transform in C++, you could do this:

auto result = new int[](10);
iota(10).map!(n => n + 1).copy(result)

And result will be filled with the results of map.