Сега, след като преминахме през какво е „Чиста функция“, можем да започнем да разглеждаме какво може да се постигне, като си играем с функциите и контекста.

Като започнем, нека поговорим за къри.

Дефиницията от Wikipedia е:

В „математика“ и „компютърни науки“ кърирането е техниката за преобразуване на „функция“, която приема множество „аргументи“ в поредица от функции, всяка от които приема един аргумент.

Така че по същество функцията с къри е функция, в която върнатата стойност е друга функция.

Прост пример би бил актуализирането на следния сумиращ код:

const sum = (a: number, b: number) => a + b;
const result = sum(10, 20);

To:

const currySum = (a: number) => (b: number) => a + b;
const result = currySum(10)(20);

В който sumfunction връща вторична функция, вместо да има двата параметъра вградени и да връща резултата веднага.

Кога и защо е добре да се използва къри?

Тази техника е особено мощна, когато искаме да предоставим контекст на функция, която ще бъде изпълнена по-късно, когато информацията няма да бъде налична.

Нека да разгледаме пример от реалния живот, като използваме React, като изградим формуляр, който улавя основната информация на потребителя.

Най-лесният начин да постигнете това е като имате onChange обратно извикване, което ще актуализира вътрешното състояние всеки път, когато потребителят напише нещо.

Проблемът е, че това не е толкова СУХО, колкото бихме могли да го приложим. С помощта на къри можем да постигнем по-просто и по-чисто решение.

Чрез създаването на функцията handleChange, която връща обратното извикване onChange, можем да спестим някои стъпки, тъй като всички актуализации ще бъдат обработени от същата логика.

Това е много често използвана техника във функционалното програмиране и е ключова за отключване на функционална композиция и функции от висок ред.

Нека сега да поговорим за функционалната композиция.

Композирането на функции е техниката за агрегиране на прости функции за създаване на по-стабилни. Също като карирането, крайният резултат от композирането на функция е друга функция.

Прост пример би бил да имаме sumи aproductфункция и искаме те да се изпълняват една след друга. Можем да ги комбинираме заедно, така че функцията за резултат винаги да е готова за използване по-късно.

const sum = (a: number) => a + 1;
const product = (a: number) => a * 2;
const composed = (a: number) => product(sum(a));
composed(1);
// 4

С Typescript можем да изградим функция за съставяне на n брой функции, като ги предаваме като параметри. Функцията изглежда така:

const compose = <T>(...functionList: Function[]) => (value: T) => functionList.reduceRight((result, fn) => fn(result), value);

Това води до по-ясен начин за агрегиране на двете функции, които искаме да бъдат изпълнени една след друга.

const composed = compose<number>(product, sum);
composed(1);
// 4

Най-изправената функция ще бъде изпълнена първа, в този случай sum ще бъде изчислено преди product.

Сега, след като научихме основите около къри и функционалната композиция, можем малко да повишим нивото. В следния кодов фрагмент имаме сценарий, при който искаме да актуализираме потребителската информация, която е разделена на три типа (информация, адрес и контакт).

Начинът, по който можем да изпълним функцията за актуализиране без това, което сме научили, е като опаковаме всеки резултат в следващата функция.

Грозно нали? И ако продължим да добавяме функции, ще стане по-трудно за четене. Така че нека го подобрим с това, което научихме.

След като създадем функцията composeUpdate по състав, можем да я използваме, за да задействаме същата актуализация на множество потребителски обекти с предварително дефинираната информация като:

const user1: TUser = {...};
const user2: TUser = {...};
const updatedUser1 = composedUpdate(user1);
const updatedUser2 = composedUpdate(user2);

Заключение

  • Кърирането е полезна техника за споделяне на контекст между множество нива на функции.
  • Композицията на функция улеснява процеса на свързване на множество процеси, които зависят от резултата от предишната стъпка.
  • Идеята за съставяне на функции може да се опише като комбиниране на множество функции с кари за създаване на по-сложна, която ще бъде изпълнена по-късно.

Тази публикация в блога е част от поредицата „Функционално програмиране с Typescript“ за това как да интегрирате принципи на функционално програмиране за вашето приложение, като същевременно го поддържате безопасно за писане с Typescript.

Въведение | Пев ‹ | "Следващия >"