Частичные функции с привязкой

Итак, недавно я обнаружил, что вы можете выполнять частичные функции/каррирование с помощью js, используя привязку. Например:

const foo = (a, b, c) => (a + (b / c))
foo.bind(null, 1, 2) //gives me (c) => (1 + (2 / c))

Однако это работает только в том случае, если части, которые вы хотите карри, в порядке. Что, если бы я хотел добиться следующего с помощью bind?

(b) => (1 + (b / 2))

Пробовал различные решения, такие как:

foo.bind(null, 1, null, 2)

Любые идеи? Можно ли это сделать с помощью vanilla es6?


person Vangogh500    schedule 05.06.2018    source источник
comment
с заполнителями вы можете взглянуть на этот вопрос: stackoverflow .com/questions/48327804/   -  person Nina Scholz    schedule 05.06.2018
comment
Существует предложение по сахару синтаксиса частичного приложения github.com/tc39/proposal-partial-application   -  person Yury Tarabanko    schedule 05.06.2018


Ответы (2)


Вы можете использовать оболочку для переупорядочения аргументов.

const
    foo = (a, b, c) => a + b / c,
    acb = (a, c, b) => foo(a, b, c);

console.log(acb.bind(null, 1, 2)(5));

person Nina Scholz    schedule 05.06.2018

В настоящее время я думаю о двух способах реализации этого (кроме обертки от @NinaSholz, которая довольно хороша):

1. Использование функции curry, которая объединяет два массива аргументов:

const foo = (a, b, c) => a + b / c;

function curry(fn, ...args) {
  return function(...newArgs) {
    const finalArgs = args.map(arg => arg || newArgs.pop());
    return fn(...finalArgs);
  };
}

const curriedFoo = curry(foo, 1, null, 2);

console.log(curriedFoo(4)) // Should print 1 + 4 / 2 = 3

Здесь мы просто отправляем null или undefined вместо параметров, которые хотим пропустить, и во втором вызове мы отправляем эти параметры по порядку.

2. Использование объектов для именованных параметров

const foo = ({a, b, c}) => a + b / c;

function curry(fn, args) {
  return (newArgs) => fn({ ...args,
    ...newArgs
  });
}

const curriedFoo = curry(foo, {
  a: 1,
  c: 2
});

console.log(curriedFoo({
  b: 4
}));

Здесь мы используем оператор ...(spread) и синтаксис объекта в сигнатуре функции для объединения двух объектов-аргументов;

person J. Pichardo    schedule 05.06.2018