Правильное карри в C # - PullRequest
       31

Правильное карри в C #

33 голосов
/ 04 января 2009

Учитывая метод DoSomething, который принимает (без параметров) функцию и обрабатывает ее некоторым образом. Есть ли лучший способ создать «перегрузки» для функций с параметрами, чем приведенный ниже фрагмент кода?

public static TResult DoSomething<TResult>(Func<TResult> func)
{
    //call func() and do something else
}

public static TResult DoSomething<T0, TResult>(
    Func<T0, TResult> func,
    T0 arg0)
{
    return DoSomething(() => func(arg0));
}

public static TResult DoSomething<T0, T1, TResult>(
    Func<T0, T1, TResult> func,
    T0 arg0, T1 arg1)
{
    return DoSomething(arg => func(arg, arg1), arg0);
}

public static TResult DoSomething<T0, T1, T2, TResult>(
    Func<T0, T1, T2, TResult> func,
    T0 arg0, T1 arg1, T2 arg2)
{
    return DoSomething(arg => func(arg, arg1, arg2), arg0);
}

1 Ответ

31 голосов
/ 04 января 2009

РЕДАКТИРОВАТЬ: Как отмечено в комментариях, это частичное применение, а не карри. Я написал в своем блоге сообщение о моем понимании разницы , что может показаться интересным людям.

Ну, это не особенно отличается - но я бы отделил каррирующую часть от "вызывающей DoSomething":

public static Func<TResult> Apply<TResult, TArg> (Func<TArg, TResult> func, TArg arg)
{
    return () => func(arg);
}

public static Func<TResult> Apply<TResult, TArg1, TArg2> (Func<TArg1, TArg2, TResult> func,
                                                          TArg1 arg1, TArg2 arg2)
{
    return () => func(arg1, arg2);
}

// etc

Тогда:

DoSomething(Apply(foo, 1));

Таким образом, вы можете повторно использовать код карри в других ситуациях - включая случаи, когда вы не хотите немедленно вызывать вновь возвращенного делегата. (Возможно, вы захотите карри это позже, например.)

...