Thread overview
taskPool.reduce vs algorithm.reduce
Jul 11
Timoses
2 days ago
Malte
July 11
Hi.

I'm trying to use taskPool.reduce with a delegate, for example:

import std.parallelism;

int main(string[] args)
{
  int f(int a, int b)
  {
    if (args.length > 1)
      return a+b;
    else
      return a-b;
  }

  auto res = taskPool.reduce!f([1, 2, 3]);

  return 0;
}

But it fails to compile (with gdc 8.1.0, dmd v2.081) complaining that

template instance reduce!(f) cannot use local 'f' as parameter to non-global template reduce(functions...)

The snippet above compiles with the reduce function from std.algorithm.

Is there a way to make the code compile with taskPool.reduce ?
(I don't want to write two functions and choosing one depending on args.length)

Why the interface difference between std.algorithm's reduce and taskPool.reduce ?

Best regards,

Dorian
July 11
On Wednesday, 11 July 2018 at 08:31:30 UTC, Dorian Haglund wrote:
>
> But it fails to compile (with gdc 8.1.0, dmd v2.081) complaining that
>
> template instance reduce!(f) cannot use local 'f' as parameter to non-global template reduce(functions...)

Congratulations! You've just run into issue 5710 [1], one of D's most annoying known bugs.

[1]: https://issues.dlang.org/show_bug.cgi?id=5710

> The snippet above compiles with the reduce function from std.algorithm.
>
> [...]
>
> Why the interface difference between std.algorithm's reduce and taskPool.reduce ?

std.algorithm.reduce is a free function, so it can accept delegates as template parameters. taskPool.reduce is a member function, so it can't.
July 11
On Wednesday, 11 July 2018 at 08:31:30 UTC, Dorian Haglund wrote:
> Hi.
>
> I'm trying to use taskPool.reduce with a delegate, for example:
>
> import std.parallelism;
>
> int main(string[] args)
> {
>   int f(int a, int b)
>   {
>     if (args.length > 1)
>       return a+b;
>     else
>       return a-b;
>   }
>
>   auto res = taskPool.reduce!f([1, 2, 3]);
>
>   return 0;
> }
>
> But it fails to compile (with gdc 8.1.0, dmd v2.081) complaining that
>
> template instance reduce!(f) cannot use local 'f' as parameter to non-global template reduce(functions...)
>
> The snippet above compiles with the reduce function from std.algorithm.
>
> Is there a way to make the code compile with taskPool.reduce ?
> (I don't want to write two functions and choosing one depending on args.length)
>
> Why the interface difference between std.algorithm's reduce and taskPool.reduce ?
>
> Best regards,
>
> Dorian

As the error message says taskPool.reduce is a non-global template. It's embedded in a taskPool struct. I can't say what the reason is that a delegate cannot be used with such a template. I'd be interested in hearing what the reason is.
(See Paul's reply).

I'm trying to trick around it, but can't get this to work...

https://run.dlang.io/is/EGbtuq

import std.parallelism;

int main(string[] args)
{
    static int f(bool cond)(int a, int b)
    {
        static if (cond)
            return a+b;
        else
            return a-b;
    }

    template getF(alias func)
    {
        auto getF(T)(T arg)
        {
            if (args.length > 1)
                return func!(f!true)(arg); // line 18
            else
                return func!(f!false)(arg); // line 20
        }
    }

    auto res = getF!(taskPool.reduce)([1,2,3]);

    return 0;
}


onlineapp.d(18): Error: need this for reduce of type @system int(int[] _param_0)
onlineapp.d(20): Error: need this for reduce of type @system int(int[] _param_0)
2 days ago
On Wednesday, 11 July 2018 at 10:07:33 UTC, Timoses wrote:
> On Wednesday, 11 July 2018 at 08:31:30 UTC, Dorian Haglund wrote:
>> [...]
>
> As the error message says taskPool.reduce is a non-global template. It's embedded in a taskPool struct. I can't say what the reason is that a delegate cannot be used with such a template. I'd be interested in hearing what the reason is.
> (See Paul's reply).
>
> I'm trying to trick around it, but can't get this to work...
>
> https://run.dlang.io/is/EGbtuq

You can make it all global: https://run.dlang.io/is/Kf8CLC

From my own experience: Use only parallel foreach and save yourself a lot of hassle. That just works.