Javascript Функция канала - почему все стандартные реализации возвращают функцию, которая принимает аргумент - PullRequest
0 голосов
/ 21 марта 2020

Я видел много реализаций для pipe в javascript. Все они написаны в функциональном программировании, начиная с функции, которая принимает в качестве аргумента все fns, а затем возвращает функцию, которая передает аргумент первой функции. Затем эта возвращаемая функция отвечает за передачу fns.

Примерно так:

pipe = (...fns) => (x) => fns.reduce((v, f) => f(v), x);

Есть ли какие-либо проблемы с написанием этой функции таким образом, что ей необходимо вернуть функция и может просто принять параметр в своих аргументах:

pipe = (x, ...fns) => fns.reduce((v, f) => f(v), x);

Будут ли они оба работать одинаково? Один лучше другого?

Ответы [ 2 ]

4 голосов
/ 21 марта 2020

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

const pipe = (x, ...fns) => fns.reduce((v, f) => f(v), x);
console.log(
  pipe(1, x => x + 2, x => x * 2),
  pipe(3, x => x + 2, x => x * 2),
);

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

const pipe = (...fns) => x => fns.reduce((v, f) => f(v), x);
const changeNum = pipe(x => x + 2, x => x * 2);
console.log(
  changeNum(1),
  changeNum(3),
);

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

Тем не менее, легче не думать о том, в какой ситуации вы находитесь, и в этом случае стандартная функция pipe для (...fns) => x => в любом случае предпочтительнее, поскольку она будет достаточно гибкой для всех ситуаций. в отличие от альтернативы.

1 голос
/ 21 марта 2020

Учитывая curry = f => x => y => f(x, y) и uncurry = f => (x, y) => f(x) (y), они одинаковы, то есть вы можете преобразовать одну форму в другую и наоборот (игнорируя параметр rest).

Но вопрос в том, почему вы обременяете себя с функцией арности на первом месте? Почему функции должны различаться по арности вообще? Если бы каждая функция принимала только один аргумент, их API был бы упрощен, и мы могли бы объединить их с меньшими ограничениями:

const fold = f => acc => xs => xs.reduce((acc, x) => f(acc) (x));
const pipe = g => f => x => f(g(x));
const flip = f => y => x => f(x) (y);
const id = x => x;

const pipen = fold(pipe) (id);
const comp = flip(pipe);
const compBin = comp(comp) (comp);
const compBin3 = compBin(compBin) (compBin);

const inc = x => x + 1;
const sqr = x => x * x;
const add = x => y => x + y;

console.log(
  "pipen",
  pipen([inc, inc, inc, inc, sqr]) (1)); // 25

console.log(
  "compBin",
  compBin(add) (add) (2) (3) (4)); // 9
  
console.log(
  "compBin3",
  compBin3(add) (add) (add) (2) (3) (4) (5)); // 14

Никто не определит comp и compBin так, как я. Это должно просто проиллюстрировать возможности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...