On Wednesday, 9 September 2015 at 07:19:06 UTC, Bahman Movaqar
wrote:
On Tuesday, 8 September 2015 at 18:45:33 UTC, Jonathan M Davis
wrote:
[...]
@Jonathan, @cym13 and @Meta
It's reasonable to use `auto`. However there are times when
you need to pass the `auto` value to another function and the
receiving function needs to know the type of its input
arguments.
In other news:
Consider the following piece of code. *Please note that I am
aware that the simple problem introduced can be solved in
several ways which are more efficient.*
immutable struct FooBar {
int x;
int y;
}
immutable(FooBar)[] foobars = [
FooBar(60, 100),
FooBar(8, 20),
FooBar(9, 15)
];
int[] nums = [20, 40, 55];
//////////////////////////////////////////
// find FooBars which:
// - x * y is greater than any `num`
// - x and y are smaller than any `num`
//////////////////////////////////////////
auto result = reduce!(
(acc, num) => acc.filter!(
fb => (fb.x < num && fb.y < num) && (fb.x * fb.y > num)
)
)(foobars, nums);
//
assert(result[0].x == 9 && result[0].y == 15);
This fails to compile with the following message:
Error: static assert "Incompatible function/seed/element:
test.__unittestL40_4.__lambda1/immutable(FooBar)[]/int"
/usr/include/dmd/phobos/std/algorithm/iteration.d(2518):
instantiated from here: reduceImpl!(false, int[],
immutable(FooBar)[])
/usr/include/dmd/phobos/std/algorithm/iteration.d(2502):
instantiated from here: reducePreImpl!(int[],
immutable(FooBar)[]) test.d(56): instantiated from here:
reduce!(immutable(FooBar)[], int[])
The only way to make it work is `.array.idup` the output of
`filter`. For example:
auto result = reduce!(
(acc, num) => acc.filter!(
fb => (fb.x < num && fb.y < num) && (fb.x * fb.y > num)
).array.idup
)(foobars, nums);
Honestly, I cannot comprehend anything out of this; why I had
to realise the lazy value and `idup` it for it to become usable
by `reduce`?
Does this mean that I am simply missing something obvious?
You are using reduce in a weird way here... I find it normal to
have to use weird internal tricks if you are trying weird things.
The way I would have written it is:
auto result = foobars.filter!(fb => nums.all!(n => (fb.x * fb.y)
> n))
.filter!(fb => nums.all!(n => fb.x < n &&
fb.y < n));
Here you don't have any weird and completely unreadable reduce
construct and don't have to realize the lazy check as
std.algorithm.searching.all is lazy too.