Jump to page: 1 2
Thread overview
std.algorithm.reduce on an array of structs
Sep 11, 2014
Colin
Sep 11, 2014
Daniel Kozak
Sep 11, 2014
Colin
Sep 11, 2014
Daniel Kozak
Sep 11, 2014
Daniel Kozak
Sep 11, 2014
bearophile
Sep 11, 2014
Daniel Kozak
Sep 11, 2014
Daniel Kozak
Sep 11, 2014
Daniel Kozak
Sep 11, 2014
monarch_dodra
Sep 11, 2014
monarch_dodra
Sep 11, 2014
Meta
Sep 11, 2014
Colin
Sep 12, 2014
Meta
Sep 11, 2014
Marc Schütz
Sep 11, 2014
Marc Schütz
September 11, 2014
I have this test code:

struct Thing {
    uint x;
}

void main(){
    uint[] ar1 = [1, 2, 3, 4, 5];
    auto min1 = ar1.reduce!((a,b) => a < b);
    writefln("%s", min1);  // prints 1 as expected

    Thing[] ar2 = [Thing(1), Thing(2), Thing(4)];
    auto min2 = ar2.reduce!((a,b) => a.x < b.x);  //  <- Wont Compile
    writefln("%s", min2);
}

The line with "Wont Compile" on it has this error message:
/usr/include/dmd/phobos/std/algorithm.d(770): Error: cannot implicitly convert expression (__lambda2(result, front(_param_1))) of type bool to Thing
/usr/include/dmd/phobos/std/algorithm.d(791): Error: template instance t.main.reduce!((a, b) => a.x < b.x).reduce!(Thing, Thing[]) error instantiating
t.d(16):        instantiated from here: reduce!(Thing[])


Any idea what I'm doing wrong here?
To me, the operation on ar2 should be pretty much identical to ar1, except for the use of the struct.
September 11, 2014
On Thursday, 11 September 2014 at 13:06:05 UTC, Colin wrote:
> I have this test code:
>
> struct Thing {
>     uint x;
> }
>
> void main(){
>     uint[] ar1 = [1, 2, 3, 4, 5];
>     auto min1 = ar1.reduce!((a,b) => a < b);
>     writefln("%s", min1);  // prints 1 as expected
>
>     Thing[] ar2 = [Thing(1), Thing(2), Thing(4)];
>     auto min2 = ar2.reduce!((a,b) => a.x < b.x);  //  <- Wont Compile
>     writefln("%s", min2);
> }
>
> The line with "Wont Compile" on it has this error message:
> /usr/include/dmd/phobos/std/algorithm.d(770): Error: cannot implicitly convert expression (__lambda2(result, front(_param_1))) of type bool to Thing
> /usr/include/dmd/phobos/std/algorithm.d(791): Error: template instance t.main.reduce!((a, b) => a.x < b.x).reduce!(Thing, Thing[]) error instantiating
> t.d(16):        instantiated from here: reduce!(Thing[])
>
>
> Any idea what I'm doing wrong here?
> To me, the operation on ar2 should be pretty much identical to ar1, except for the use of the struct.


You are try to put uint to Thing. This is corect version:

import std.stdio;
import std.algorithm;

struct Thing {
	uint x;
}

void main(){
	uint[] ar1 = [1, 2, 3, 4, 5];
	auto min1 = ar1.reduce!((a,b) => a < b);
	writefln("%s", min1);  // prints 1 as expected
	
	Thing[] ar2 = [Thing(1), Thing(2), Thing(4)];
	auto min2 = ar2.reduce!((a,b) => a.x < b.x ? a : b);  //  <-
Wont Compile
	writefln("%s", min2);
}
September 11, 2014
On Thursday, 11 September 2014 at 13:06:05 UTC, Colin wrote:
> I have this test code:
>
> struct Thing {
>     uint x;
> }
>
> void main(){
>     uint[] ar1 = [1, 2, 3, 4, 5];
>     auto min1 = ar1.reduce!((a,b) => a < b);
>     writefln("%s", min1);  // prints 1 as expected
>
>     Thing[] ar2 = [Thing(1), Thing(2), Thing(4)];
>     auto min2 = ar2.reduce!((a,b) => a.x < b.x);  //  <- Wont Compile
>     writefln("%s", min2);
> }
>
> The line with "Wont Compile" on it has this error message:
> /usr/include/dmd/phobos/std/algorithm.d(770): Error: cannot implicitly convert expression (__lambda2(result, front(_param_1))) of type bool to Thing
> /usr/include/dmd/phobos/std/algorithm.d(791): Error: template instance t.main.reduce!((a, b) => a.x < b.x).reduce!(Thing, Thing[]) error instantiating
> t.d(16):        instantiated from here: reduce!(Thing[])
>
>
> Any idea what I'm doing wrong here?
> To me, the operation on ar2 should be pretty much identical to ar1, except for the use of the struct.

I think you want to use `filter()` (for both Thing and uint), not `reduce()`. The former produces a range with only the elements that match the predicate, while the latter produces _one_ element according to the given rules, e.g.

    my_int_array.reduce!((result,a) => result+a);

produces the sum of all elements. In your example, the first use only compiles because `bool` happens to be implicitly convertible to `uint`.
September 11, 2014
On Thursday, 11 September 2014 at 13:28:37 UTC, Marc Schütz wrote:
> On Thursday, 11 September 2014 at 13:06:05 UTC, Colin wrote:
>> I have this test code:
>>
>> struct Thing {
>>    uint x;
>> }
>>
>> void main(){
>>    uint[] ar1 = [1, 2, 3, 4, 5];
>>    auto min1 = ar1.reduce!((a,b) => a < b);
>>    writefln("%s", min1);  // prints 1 as expected
>>
>>    Thing[] ar2 = [Thing(1), Thing(2), Thing(4)];
>>    auto min2 = ar2.reduce!((a,b) => a.x < b.x);  //  <- Wont Compile
>>    writefln("%s", min2);
>> }
>>
>> The line with "Wont Compile" on it has this error message:
>> /usr/include/dmd/phobos/std/algorithm.d(770): Error: cannot implicitly convert expression (__lambda2(result, front(_param_1))) of type bool to Thing
>> /usr/include/dmd/phobos/std/algorithm.d(791): Error: template instance t.main.reduce!((a, b) => a.x < b.x).reduce!(Thing, Thing[]) error instantiating
>> t.d(16):        instantiated from here: reduce!(Thing[])
>>
>>
>> Any idea what I'm doing wrong here?
>> To me, the operation on ar2 should be pretty much identical to ar1, except for the use of the struct.
>
> I think you want to use `filter()` (for both Thing and uint), not `reduce()`.

Scratch that, `filter()` doesn't make sense here, of course. The rest is still valid:

> The former produces a range with only the elements that match the predicate, while the latter produces _one_ element according to the given rules, e.g.
>
>     my_int_array.reduce!((result,a) => result+a);
>
> produces the sum of all elements. In your example, the first use only compiles because `bool` happens to be implicitly convertible to `uint`.
September 11, 2014
On Thursday, 11 September 2014 at 13:27:39 UTC, Daniel Kozak wrote:
> On Thursday, 11 September 2014 at 13:06:05 UTC, Colin wrote:
>> I have this test code:
>>
>> struct Thing {
>>    uint x;
>> }
>>
>> void main(){
>>    uint[] ar1 = [1, 2, 3, 4, 5];
>>    auto min1 = ar1.reduce!((a,b) => a < b);
>>    writefln("%s", min1);  // prints 1 as expected
>>
>>    Thing[] ar2 = [Thing(1), Thing(2), Thing(4)];
>>    auto min2 = ar2.reduce!((a,b) => a.x < b.x);  //  <- Wont Compile
>>    writefln("%s", min2);
>> }
>>
>> The line with "Wont Compile" on it has this error message:
>> /usr/include/dmd/phobos/std/algorithm.d(770): Error: cannot implicitly convert expression (__lambda2(result, front(_param_1))) of type bool to Thing
>> /usr/include/dmd/phobos/std/algorithm.d(791): Error: template instance t.main.reduce!((a, b) => a.x < b.x).reduce!(Thing, Thing[]) error instantiating
>> t.d(16):        instantiated from here: reduce!(Thing[])
>>
>>
>> Any idea what I'm doing wrong here?
>> To me, the operation on ar2 should be pretty much identical to ar1, except for the use of the struct.
>
>
> You are try to put uint to Thing. This is corect version:
>
> import std.stdio;
> import std.algorithm;
>
> struct Thing {
> 	uint x;
> }
>
> void main(){
> 	uint[] ar1 = [1, 2, 3, 4, 5];
> 	auto min1 = ar1.reduce!((a,b) => a < b);
> 	writefln("%s", min1);  // prints 1 as expected
> 	
> 	Thing[] ar2 = [Thing(1), Thing(2), Thing(4)];
> 	auto min2 = ar2.reduce!((a,b) => a.x < b.x ? a : b);  //  <-
> Wont Compile
> 	writefln("%s", min2);
> }

Ah ok. I get it.

Thanks daniel!
September 11, 2014
On Thursday, 11 September 2014 at 14:18:31 UTC, Colin wrote:
>
> Ah ok. I get it.
>
> Thanks daniel!

a quiet better version:

import std.stdio;
import std.algorithm;

struct Thing {
	uint x;
	alias x this;
}

void main(){
	uint[] ar1 = [1, 2, 3, 4, 5];
	auto min1 = ar1.reduce!((a,b) => min(a,b));
	writefln("%s", min1);
	
	Thing[] ar2 = [Thing(1), Thing(2), Thing(4)];
	auto min2 = ar2.reduce!((a,b) => min(a,b));
	writefln("%s", min2);
}

September 11, 2014
On Thursday, 11 September 2014 at 14:39:53 UTC, Daniel Kozak wrote:
> On Thursday, 11 September 2014 at 14:18:31 UTC, Colin wrote:
>>
>> Ah ok. I get it.
>>
>> Thanks daniel!
>
> a quiet better version:
>
> import std.stdio;
> import std.algorithm;
>
> struct Thing {
> 	uint x;
> 	alias x this;
> }
>
> void main(){
> 	uint[] ar1 = [1, 2, 3, 4, 5];
> 	auto min1 = ar1.reduce!((a,b) => min(a,b));
> 	writefln("%s", min1);
> 	
> 	Thing[] ar2 = [Thing(1), Thing(2), Thing(4)];
> 	auto min2 = ar2.reduce!((a,b) => min(a,b));
> 	writefln("%s", min2);
> }

s/quiet/quite/
September 11, 2014
Daniel Kozak:

You can just use min:

import std.stdio, std.algorithm;

struct Thing {
    uint x;
    alias x this;
}

alias minimum = reduce!min;

void main() {
	immutable ar1 = [10, 20, 30, 40, 50];
	ar1.minimum.writeln;

	immutable ar2 = [Thing(10), Thing(20), Thing(40)];
	ar2.minimum.writeln;
}

Bye,
bearophile
September 11, 2014
V Thu, 11 Sep 2014 14:49:02 +0000
bearophile via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com>
napsáno:

> Daniel Kozak:
> 
> You can just use min:
> 
> import std.stdio, std.algorithm;
> 
> struct Thing {
>      uint x;
>      alias x this;
> }
> 
> alias minimum = reduce!min;
> 
> void main() {
> 	immutable ar1 = [10, 20, 30, 40, 50];
> 	ar1.minimum.writeln;
> 
> 	immutable ar2 = [Thing(10), Thing(20), Thing(40)];
> 	ar2.minimum.writeln;
> }
> 
> Bye,
> bearophile

Yep, this look the most idiomatic :).

Why there is no phobos function for minimum of array(range)?

September 11, 2014
On Thursday, 11 September 2014 at 14:56:00 UTC, Daniel Kozak via Digitalmars-d-learn wrote:
> V Thu, 11 Sep 2014 14:49:02 +0000
> bearophile via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com>
> napsáno:
>
>> Daniel Kozak:
>> 
>> You can just use min:
>> 
>> import std.stdio, std.algorithm;
>> 
>> struct Thing {
>>      uint x;
>>      alias x this;
>> }
>> 
>> alias minimum = reduce!min;
>> 
>> void main() {
>> 	immutable ar1 = [10, 20, 30, 40, 50];
>> 	ar1.minimum.writeln;
>> 
>> 	immutable ar2 = [Thing(10), Thing(20), Thing(40)];
>> 	ar2.minimum.writeln;
>> }
>> 
>> Bye,
>> bearophile
>
> Yep, this look the most idiomatic :).
>
> Why there is no phobos function for minimum of array(range)?

or use alias minimum = reduce!"a < b";
;)
« First   ‹ Prev
1 2