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.

Reply via email to