Thread overview
Passing a function (with arguments) as function input
Apr 23, 2012
Ali Çehreli
Apr 23, 2012
Jakob Ovrum
April 22, 2012
Is there a way in which to pass a function as input to another function, with the arguments of the first function already determined?

The case I'm thinking of is one where I have a function which wants to take a random number generation scheme, and use it on several occasions, without having any info on that scheme or its parameters.

Here's a little test attempt I made:

////////////////////////////////////////////////////
import std.random, std.range, std.stdio;

void printRandomNumbers(RandomNumberGenerator)(RandomNumberGenerator rng, size_t n)
{
      foreach(i; 0..n)
            writeln(rng);
}

void main()
{
      foreach(double upper; iota(1.0, 2.0, 0.2) ) {
            double delegate() rng = () {
                  return uniform(0.0, 1.0);
            };

            printRandomNumbers(rng,10);
      }
}
////////////////////////////////////////////////////

... which just prints out: "double delegate()" over many lines.

What am I doing wrong here?  And is there any way to avoid the messy business of defining a delegate and just hand over uniform(0.0, 1.0) ... ?
April 23, 2012
On 04/22/2012 04:19 PM, Joseph Rushton Wakeling wrote:
> Is there a way in which to pass a function as input to another function,
> with the arguments of the first function already determined?
>
> The case I'm thinking of is one where I have a function which wants to
> take a random number generation scheme, and use it on several occasions,
> without having any info on that scheme or its parameters.
>
> Here's a little test attempt I made:
>
> ////////////////////////////////////////////////////
> import std.random, std.range, std.stdio;
>
> void printRandomNumbers(RandomNumberGenerator)(RandomNumberGenerator
> rng, size_t n)
> {
> foreach(i; 0..n)
> writeln(rng);

You just need to call the delegate with the function call syntax:

          writeln(rng());

Ali
April 23, 2012
On Sunday, 22 April 2012 at 23:19:52 UTC, Joseph Rushton Wakeling wrote:
> ////////////////////////////////////////////////////
> import std.random, std.range, std.stdio;
>
> void printRandomNumbers(RandomNumberGenerator)(RandomNumberGenerator rng, size_t n)
> {
>       foreach(i; 0..n)
>             writeln(rng);
> }
>
> void main()
> {
>       foreach(double upper; iota(1.0, 2.0, 0.2) ) {
>             double delegate() rng = () {
>                   return uniform(0.0, 1.0);
>             };
>
>             printRandomNumbers(rng,10);
>       }
> }
> ////////////////////////////////////////////////////
>
> ... which just prints out: "double delegate()" over many lines.
>
> What am I doing wrong here?  And is there any way to avoid the messy business of defining a delegate and just hand over uniform(0.0, 1.0) ... ?

import std.random, std.range, std.stdio;

void printRandomNumbers(double delegate() rng, size_t n)
{
	foreach(i; 0..n)
		writeln(rng());
}

void main()
{
	foreach(upper; iota(1.0, 2.0, 0.2) )
		printRandomNumbers(() => uniform(0.0, 1.0), 10);
}


Although I wouldn't recommend it, you can also use a lazy parameter to obviate the lambda syntax:

import std.random, std.range, std.stdio;

void printRandomNumbers(lazy double rng, size_t n)
{
	foreach(i; 0..n)
		writeln(rng());
}

void main()
{
	foreach(upper; iota(1.0, 2.0, 0.2) )
		printRandomNumbers(uniform(0.0, 1.0), 10);
}