В чем преимущество карри?
Прежде всего, давайте уточним некоторые термины. Люди используют «каррирование» для обозначения обоих , переформулирующих метод двух параметров в методы одного параметра, который возвращает метод одного параметра и частичное применение метода двух параметров для создания метода один параметр . Очевидно, что эти две задачи тесно связаны, и, следовательно, путаница. Говоря формально, следует ограничить «карри» ссылками на первое определение, но при разговоре неформально любое из них является обычным.
Итак, если у вас есть метод:
static int Add(int x, int y) { return x + y; }
Вы можете назвать это так:
int result = Add(2, 3); // 5
Вы можете использовать метод Add
:
static Func<int, int> MakeAdder(int x) { return y => Add(x, y); }
и сейчас:
Func<int, int> addTwo = MakeAdder(2);
int result = addTwo(3); // 5
Частичное приложение иногда также называют «карри», когда речь идет неформально, потому что оно явно связано:
Func<int, int> addTwo = y=>Add(2,y);
int result = addTwo(3);
Вы можете сделать машину, которая сделает этот процесс за вас:
static Func<B, R> PartiallyApply<A, B, R>(Func<A, B, R> f, A a)
{
return (B b)=>f(a, b);
}
...
Func<int, int> addTwo = PartiallyApply<int, int, int>(Add, 2);
int result = addTwo(3); // 5
Итак, теперь мы подходим к вашему вопросу:
В чем преимущество использования карри?
Преимущество любой техники в том, что она дает вам больше гибкости в работе с методами.
Например, предположим, что вы пишете реализацию алгоритма поиска пути. Возможно, у вас уже есть вспомогательный метод, который дает приблизительное расстояние между двумя точками:
static double ApproximateDistance(Point p1, Point p2) { ... }
Но когда вы на самом деле строите алгоритм, вам часто нужно знать, каково расстояние между текущим местоположением и фиксированной конечной точкой . В чем нуждается алгоритм равен Func<Point, double>
- каково расстояние от местоположения до фиксированной конечной точки? Что у вас есть Func<Point, Point, double>
. Как вы собираетесь превратить то, что у вас есть, в то, что вам нужно? С частичным применением; Вы частично применяете фиксированную конечную точку в качестве первого аргумента к методу приблизительного расстояния, и вы получаете функцию, которая соответствует потребностям вашего алгоритма поиска пути:
Func<Point, double> distanceFinder = PartiallyApply<Point, Point, double>(ApproximateDistance, givenEndPoint);
Если метод ApproximateDistance был карри в первую очередь:
static Func<Point, double> MakeApproximateDistanceFinder(Point p1) { ... }
Тогда вам не нужно будет подавать частичное заявление самостоятельно; Вы просто позвоните MakeApproximateDistanceFinder
с фиксированной конечной точкой, и все будет готово.
Func<Point, double> distanceFinder = MakeApproximateDistanceFinder(givenEndPoint);