Лучший способ создать функцию, которая генерирует функцию в C # - PullRequest
7 голосов
/ 24 января 2012

F # предоставляет функцию, где функция может возвращать другую функцию.

Пример функции, генерирующей функцию в F #, выглядит следующим образом:

let powerFunctionGenarator baseNumber = (fun exponent -> baseNumber ** exponent);

let powerOfTwo = powerFunctionGenarator 2.0;

let powerOfThree = powerFunctionGenarator 3.0;

let power2 = powerOfTwo 10.0;
let power3 = powerOfThree 10.0;

printfn "%f" power2;
printfn "%f" power3;

Лучший способ добиться того же в C # - это:

class Program
{
    delegate double PowerOf2(double exponent);
    delegate double PowerOf3(double exponent);
    delegate double PowerOfN(double n, double exponent);

    static void Main(string[] args)
    {
        PowerOfN powerOfN = (a, b) => { return Math.Pow(a,b) ; };
        PowerOf2 powerOf2 = (a) => { return powerOfN(2, a); };
        PowerOf3 powerOf3 = (a) => { return powerOfN(3, a); };

        double result = powerOf2(10);
        Console.WriteLine(result);
        result = powerOf3(10);
        Console.WriteLine(result);
    }
}

Есть ли другой способ (или лучший способ) сделать это?

Ответы [ 4 ]

10 голосов
/ 24 января 2012

Конечно, это просто в C #:

using System;
class P
{
  static void Main()
  {
      Func<double, Func<double, double>> powerFunctionGenerator = 
          baseNumber => exponent => Math.Pow(baseNumber, exponent);  

      Func<double, double> powerOfTwo = powerFunctionGenerator(2.0);
      Func<double, double> powerOfThree = powerFunctionGenerator(3.0);
      double power2 = powerOfTwo(10.0); 
      double power3 = powerOfThree(10.0);
      Console.WriteLine(power2); 
      Console.WriteLine(power3);
  }
}

Легко, peasy.И если вам не нравится ввод манифеста, большинство из них можно заменить на var.

6 голосов
/ 24 января 2012

Вы можете написать функцию для карри другой функции. Неудобство заключается в том, что вам придется создавать все необходимые вам перегрузки.

Пример:

using System;

class Program {

    static Func<T2, TRes> Curry<T1, T2, TRes>(Func<T1, T2, TRes> f, T1 t1) {
        return (t2) => f(t1, t2);
    }

    static double PowerFunction(double d1, double d2) {
        return Math.Pow(d1, d2);
    }

    static void Main(string[] args) {
        var powerOf2 = Curry<double, double, double>(PowerFunction, 2);
        double r = powerOf2(3);
    }
}
3 голосов
/ 24 января 2012

Почти буквальный перевод вашего оригинального F # на C #:

Func<double,Func<double,double>> powerFunctionGenerator = 
    (baseNumber) => ((exponent) => Math.Pow(baseNumber, exponent));

var powerOfTwo = powerFunctionGenarator(2.0);

var powerOfThree = powerFunctionGenarator(3.0);

var power2 = powerOfTwo(10.0);
var power3 = powerOfThree(10.0);

Console.WriteLine(power2);
Console.WriteLine(power3);
1 голос
/ 24 января 2012

Если вы спрашиваете, как переписать powerFunctionGenarator в C #, вы можете сделать это довольно просто:

Func<double, double> powerFunctionGenarator(double baseNumber)
{
    return exponent => Math.Pow(baseNumber, exponent);
}

Вы не можете поместить объявление метода как это внутри другого метода в C #. Но если вы хотите сделать это, вы можете использовать лямбду в лямбде, как предложил sblom:

Func<double, Func<double, double>> powerFunctionGenerator =
    baseNumber => exponent => Math.Pow(baseNumber, exponent);

Что эквивалентно следующему коду в F #:

let powerFunctionGenarator = fun baseNumber -> (fun exponent -> baseNumber ** exponent)
...