Обратные вызовы JavaScript и функциональное программирование
"Функциональное программирование описывает только операции, выполняемые на входах в программы, без использования временных переменных для хранения промежуточных результатов".
Вопрос заключается в том, как применять функциональное программирование и использовать асинхронные модули, которые используют обратные вызовы.
В некоторых случаях у вас был обратный вызов для доступа к переменной, которая выполняет функцию, вызывающую ссылки на async, но сигнатура обратного вызова уже определена.
Пример:
function printSum(file,a){
//var fs =....
var c = a+b;
fs.readFile(file,function cb(err,result){
print(a+result);///but wait, I can't access a......
});
}
Конечно, я могу получить доступ к a, но это будет против парадигмы чистого функционального программирования
Ответы
Ответ 1
fs.readFile(file, (function cb(err,result){
print(this.a+result);
}).bind({a: a});
Просто введите context
переменными и областью действия в функцию, если вы должны.
Потому что вы жалуетесь на API
fs.readFile(file, (function cb(a, err,result){
print(a+result);
}).bind(null, a);
Он назвал currying. Это намного больше FP.
Ответ 2
Я думаю, что проблема в том, что вы неправильно понимаете, что они подразумевают под использованием промежуточного значения (или они искажают его, я не читал ссылку). Считайте, что переменная в функциональном языке является definition
чего-то, и это определение не может измениться. Совершенно приемлемо использовать имена для значений/формул в функциональном программировании, если они не меняются.
function calculate(a,b,c) {
// here we define an name to (a+b) so that we can use it later
// there nothing wrong with this "functionally", since we don't
// change it definition later
d = a + b;
return c * d;
}
С другой стороны, следующее не будет нормально, функционально
function sum(listofvalues) {
sum = 0;
foreach value in listofvalues
// this is bad, since we're re-defining "sum"
sum += value;
return sum
}
Что-то ближе к тому, что у вас было в коде... подумайте, что у вас есть вызов функции map that takes a list of things and a function to apply to a thing and returns a new list of things. It perfectly acceptable to say:
function add_value(amount) {
amount_to_incr = amount * 2;
return function(amount, value) {
// here we're using that "amount" value provided to us
// the function returned will always return the same value for the same
// input... its "referentially transparent"
// and it uses the "intermediate" value of amount_to_incr... however, since
// that value doesn't change, it fine
return amount_to_incr + value;
}
}
map [1,2,3] add_value(2) ;// -> [3,4,5]
Ответ 3
function printSum(file, a) {
//var fs =....
var c = a + b;
fs.readFile(file, function cb(err, result, aa = a) {
print(aa + result);
});
}
В настоящее время с параметрами по умолчанию, a может быть передано в обратный вызов.