2017-02-10 32 views
1

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

Если f3(x) должна быть такой же, как f1(f2(x)) затем f3 = _.flowRight(f1,f2);

Если f3(x,y) должна быть такой же, как f1(x, f2(y)) тогда ...?

(Прецедент является состав Node.js/экспресс-функции промежуточного программного обеспечения.)

+0

Вчера я написал ответ о потоке лодаша. Я думаю, вы найдете это очень полезным. Некоторые функции не предназначены для составления: http://stackoverflow.com/a/42139851/633183 – naomik

+0

Я написал еще один ответ час назад о композиции в существующей кодовой базе.Я думаю, вы найдете это актуальным для темы thsi: http://stackoverflow.com/a/42164779/633183 – naomik

+0

Ваша «проблема» заключается в том, что вы пытаетесь составить функции различных * arity *; унарная функция с двоичной функцией. Функциональная композиция работает лучше всего, когда унарные функции используются исключительно. Короткий ответ: 'const f3 = (x, y) => f1 (x, f2 (y))' - пусть простое просто. – naomik

ответ

2

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

Почему бы просто не написать свою собственную вспомогательную функцию для этого?

function composeFuncs(f1, f2) { 
 
    return function(x, y) { 
 
    return f1.call(this, x, f2.call(this, y)); 
 
    }; 
 
} 
 

 
var myObj = { 
 
    add: function(val1, val2) { 
 
    return this.myVal + val1 + val2 
 
    }, 
 
    mult: function(val) { 
 
    return this.myVal * val 
 
    }, 
 
    myVal: 7 
 
}; 
 

 
myObj.newFunc = composeFuncs(myObj.add, myObj.mult); 
 

 
// 7 + 1 + 7 * 2 = 22 
 
console.log(myObj.newFunc(1, 2));

Edit: обновление для обработки this так же, как _.flowRight делает.

+0

Конечно, я мог бы это сделать, но мне, вероятно, придется позаботиться об обработке «этого», как делает _.flowRight от lodash. Поскольку я совершенно новичок в том, чтобы делать многое в функциональном программировании, я думал, может быть хорошо известный образец для чего-то вроде того, что мне нужно. :) – matths

+0

@matths Изменено, чтобы включить 'this' распространение. Не могли бы вы привести пример того, где вы хотите это использовать? Я не знаком с хорошо известной схемой этого, но может быть и такой. – JLRishe

+0

В настоящее время я пишу экспресс/соединение как функции промежуточного программного обеспечения, например. один из них - метод (m, handler), где m может быть получен, отправлен, помещен и т. д., а другой может быть «path (p, handler)». Состав должен быть 'request (m, p, handler)', который запускает 'метод (m, путь (p, обработчик))'. Каждое возвращаемое значение промежуточного программного обеспечения само по себе является обработкой. Я не уверен, я могу объяснить достаточно хорошо. – matths

4

На следующих изображениях я использую {_} в качестве заполнителя для значения. Думайте об этом как отверстие в коде, где мы передаем нечто.

Хорошо давайте представим, что ваша функция будет иметь, чтобы сделать ...

a bad dream

  • ли это кажется как родовое преобразование? т. е. как вы думаете, мы можем использовать это во многих местах? – Функциональное программирование способствует построению функций, которые могут многократно использоваться и могут быть объединены различными способами.
  • В чем разница между f1 и f2? f1 - это унарная функция, которая получит только один аргумент, f2 - это двоичная функция, которая получит два. Ты собираешься вспомнить, кто из них идет?
  • Что определяет положение, которое f1(x) размещается в f2?
    • Сравнить f2(y,f1(x)) ...
    • к f2(f1(x),y)
    • является одним из тех, кто более полезен, чем другой?
    • Вы собираетесь запомнить, какая позиция f1 получает?

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

a nigthmare

  • Есть даже картина здесь? Может быть, но вы до сих пор неловко унарную функцию f1, что только получает один ARG, в то время как f2 и f3 каждый получает 2
  • Верно ли, что f2 и f3 собираются нужно значение предыдущего вызова функции на правой стороне всегда?
    • Сравнить f3(z,f2(y,f1(x)))
    • к f3(f2(y,f1(x)),z)
    • Может f3 потребности в цепи слева, но f2 цепи от права?
    • Я не могу представить себе весь API двоичных функций волшебным нужен прикованные аргументы в том же месте
  • Вы уже смешанными унарный с бинарными функциями в вашей композиции; зачем произвольно ограничивать его только функциями этого типа? Как насчет функции из 3 или более аргументов?

Ответ самостоятельно реализовать

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

Возвращаясь к коду сейчас, если f3 нужно имя, и это сочетание f1, f2 и двумя параметрами, оно должно быть ясно выражено, как и hellip;

const f3 = (x,y) => f1(x, f2(y)) 

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


«Так есть ли способ, чтобы составить функции различной арности?»

Несомненно, существует несколько приемов различной практичности. Я продемонстрирую использование высокой практической partial функции здесь

const partial = (f,...xs) => (...ys) => f(...xs, ...ys) 
 

 
const add = (x,y) => x + y 
 

 
const mult = (x,y) => x * y 
 

 
const sq = x => mult (x,x) 
 

 
// R.I.P. lodash.flowRight 
 
const compose = ([f,...fs]) => x => 
 
    f === undefined ? x : f (compose (fs) (x)) 
 
        
 
let f = compose([partial(add, 1), sq, partial(mult, 3)]) 
 

 
console.log(f(2)) 
 
// add(1, square(mult(3, 2))) 
 
// add(1, square(6)) 
 
// add(1, 36) 
 
// => 37

О, кстати, мы заменили Lodash в flowRight (обертку комплекса flow) с одной строки кода.