Каррирование функций: три строки кода реализуют add(1)(2)(3)

JavaScript

предисловие

Эта статья в основном с точки зрения 3W (что, как, почему), чтобы объяснить простым для понимания образом, что такое каррирование функций и как его реализовать с помощью трех строк кода.add(1)(2)(3)Это очень распространенный вопрос на собеседовании.

Что такое функция каррирования (карри)

Каррирование функций — это концепция функционального программирования. Концепция карри проста: вызовите функцию только с подмножеством аргументов и заставьте ее вернуть функцию для обработки остальных аргументов.

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

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

const add = (x, y) => x + y;
add(1, 2);

Измените его на функцию, которая принимает только один параметр за раз.

const add = x => y => x + y;
add(1)(2);

Каррирование, неизменяемые типы данных, чистые функции и т. д. — все это концепции функционального программирования. Эти концепции распространены в React, потому что в React много концепций функционального программирования. Чтобы узнать больше о том, что такое функциональное программирование, см.Руководство по функциональному программированию JS

add(1)(2)(3)

Мы можем сначала попробовать написать add(1)(2)(3)

const add = x => y => z => x + y + z;
console.log(add(1)(2)(3));

Это не кажется таким уж сложным, но что, если запрос интервьюера состоит в том, чтобы реализовать функцию добавления, которая одновременно поддерживает следующие варианты использования?

add(1, 2, 3);
add(1, 2)(3);
add(1)(2, 3);

Если мы по-прежнему будем следовать изложенному выше ходу мыслей, нужно ли нам писать много...

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

В чем основная идея? Чтобы определить, больше или равно ли количество параметров (args.length), переданных в функцию, количеству параметров, требуемых исходной функцией (fn.length), или равно, если да, то выполнить текущую функция; если меньше, то вернуть функцию.

const curry = (fn, ...args) => 
    // 函数的参数个数可以直接通过函数数的.length属性来访问
    args.length >= fn.length // 这个判断很关键!!!
    // 传入的参数大于等于原始函数fn的参数个数,则直接执行该函数
    ? fn(...args)
    /**
     * 传入的参数小于原始函数fn的参数个数时
     * 则继续对当前函数进行柯里化,返回一个接受所有参数(当前参数和剩余参数) 的函数
    */
    : (..._args) => curry(fn, ...args, ..._args);

function add1(x, y, z) {
    return x + y + z;
}
const add = curry(add1);
console.log(add(1, 2, 3));
console.log(add(1)(2)(3));
console.log(add(1, 2)(3));
console.log(add(1)(2, 3));

Ramda

RamdaВсе функции поддерживают каррирование. Другими словами, все многопараметрические функции могут по умолчанию использовать однопараметрические функции.

Или возьмем пример выше

const addThreeNumbers = (x, y, z) => x + y + z;
const curriedAddaddThreeNumbers = R.curry(addThreeNumbers);
const f = curriedAddaddThreeNumbers(1, 2);
console.log(f(3));

известныйlodashФункция каррирования также предусмотрена в , тогда она иRamdaкакие различия есть

lodashЭто очень мощная библиотека функций инструментов, таких как дросселирование, защита от сотрясений, глубокое копирование и т. д. Пока введен lodash, мы можем использовать его напрямую.Ramdaэто библиотека стилей функционального программирования.

Что делает каррирование?

Есть 3 основные функции:Повторное использование параметра,вернуться пораньшеиотложенное исполнение

Кратко объясним: Повторное использование параметра: возьмите вышеуказанноеfНапример, этой функции нужно передать только один параметрz, выполнить, результат1 + 2 + zВ результате два параметра 1 и 2 можно использовать повторно напрямую.

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

Ссылаться на

Категории