#javascript #currying
#javascript #каррирование
Вопрос:
У меня возникла проблема с одним из заданий в моем курсе программирования на javascript.
Назначение:
Создайте функцию с именем «calculate», которая ожидает три функции в качестве параметров и при вызове возвращает одну из этих функций в качестве результата.
Каждый раз, когда вы вызываете
let result = calculate(add, subtract, multiply)(1,3)
она должна возвращать другой результат.
Я пробовал разные подходы и получал разные ошибки, такие как вычисление не является функцией или умножение не определено.
Это то, что я пробовал до сих пор:
function add(num1, num2){
return num1 num2;
}
function subtract(num1, num2){
return num1 - num2;
}
function multiply(num1, num2){
return num1 * num2;
}
function calculate(add, subtract, multiply){
let randNum = Math.floor(Math.random() * 3) 1
switch(randNum){
case 1:
let add = add(num1, num2)
break;
case 2:
let subtract = subtract(num1, num2);
break;
case 3:
let multiply = multiply(num1, num2);
break;
}
}
let result = calculate(add(2,4), subtract(2,4), multiply(2,4))
console.log(result);
Я провел некоторое исследование по каррированию, но я не вижу, в чем я ошибаюсь. Любая помощь будет с благодарностью оценена.
Комментарии:
1. «Каждый раз, когда вы call…it должен вернуть другой результат «. Это не очень четкое назначение. Что она должна вернуть в четвертый раз, если я уже вернул результаты сложения, вычитания и умножения?
2. Это (или ответ на него) на самом деле не является примером каррирования, если только у вашего инструктора нет для этого действительно излишне сложного решения. Простое решение, если используется случайность, может легко быть однострочным.
3. Может быть, я плохо перевел задание. Я думаю, что требуется, чтобы при вызове функции calculate она случайным образом выбирала одну из 3 функций, которые она получила в качестве параметров.
Ответ №1:
Это не лучший пример для обучения каррированию. Я думаю, что инструктор / курс пытается донести здесь то, что когда вы делаете:
let result = calculate(add, subtract, multiply)(1,3)
вы вызываете функцию ( calculate
), которая возвращает функцию (одну из трех, которые вы ей передаете, я думаю, выбранную случайным образом, хотя назначение неясно), а затем вы вызываете эту функцию (используя (1,3)
результат calculate(...)
вызова.
calculate
может быть однострочным:
function calculate(...fns) {
return fns[Math.floor(Math.random() * fns.length)];
}
или в ES5:
function calculate() {
return arguments[Math.floor(Math.random() * arguments.length)];
}
Живой пример:
function add(num1, num2){
return num1 num2;
}
function subtract(num1, num2){
return num1 - num2;
}
function multiply(num1, num2){
return num1 * num2;
}
function calculate(...fns) {
return fns[Math.floor(Math.random() * fns.length)];
}
let result = calculate(add, subtract, multiply)(1,3);
console.log(result);
Более полезным примером для обучения каррированию было бы:
let result = calculate(add, subtract, multiply)(1)(3);
// ----------------------------------------------^^
Обратите внимание, что мы вызываем результат calculate
with 1
, а затем вызываем результат этого with 3
. Затем calculate
нужно будет обернуть выбранную функцию в другую функцию, которая собирает 1
, а затем ожидает вызова с помощью 3
:
function calculate(...fns) {
const fn = fns[Math.floor(Math.random() * fns.length)];
return (a) => {
return (b) => {
return fn(a, b);
};
};
}
или более кратко, но менее четко:
function calculate(...fns) {
const fn = fns[Math.floor(Math.random() * fns.length)];
return (a) => (b) => fn(a, b);
}
Живой пример:
function add(num1, num2){
return num1 num2;
}
function subtract(num1, num2){
return num1 - num2;
}
function multiply(num1, num2){
return num1 * num2;
}
function calculate(...fns) {
const fn = fns[Math.floor(Math.random() * fns.length)];
return (a) => (b) => fn(a, b);
}
let result = calculate(add, subtract, multiply)(1)(3);
console.log(result);
Функция, возвращаемая calculate
при вызове, запоминает a
и возвращает новую функцию; эта функция при вызове получает b
и вызывает fn(a, b)
для получения результата.
В этом примере функция выбирается заранее, но она также может быть выбрана в конце:
function calculate(...fns) {
return (a) => (b) => fns[Math.floor(Math.random() * fns.length)](a, b);
}
Живой пример:
function add(num1, num2){
return num1 num2;
}
function subtract(num1, num2){
return num1 - num2;
}
function multiply(num1, num2){
return num1 * num2;
}
function calculate(...fns) {
return (a) => (b) => fns[Math.floor(Math.random() * fns.length)](a, b);
}
let result = calculate(add, subtract, multiply)(1)(3);
console.log(result);
Комментарии:
1. «или более кратко, но менее четко» , пока вы не привыкнете к функциям со стрелками. Однако даже тогда, если вложение продолжается, ясность может пострадать (по крайней мере, для меня).
Ответ №2:
Вы можете взять случайную функцию из аргументов и вернуть эту функцию для другого вызова с параметрами.
const
add = (a, b) => a b,
subtract = (a, b) => a - b,
multiply = (a, b) => a * b,
calculate = (...args) => args[Math.floor(Math.random() * args.length)];
let result = calculate(add, subtract, multiply)(1, 3);
console.log(result);
Ответ №3:
calculate должен возвращать одну из функций, поэтому результат функции calculate должен вызываться с фактическими параметрами:
function add(num1, num2){
return num1 num2;
}
function subtract(num1, num2){
return num1 - num2;
}
function multiply(num1, num2){
return num1 * num2;
}
function calculate(add, subtract, multiply){
let randNum = Math.floor(Math.random() * 3) 1
switch(randNum){
case 1:
return add
break;
case 2:
return subtract
break;
case 3:
return multiply
break;
}
}
console.log(calculate(add, subtract, multiply)(2, 4));
Комментарии:
1. Дампы кода не являются полезными ответами. Скажите, что вы сделали и почему . (Перед публикацией, а не как редактирование.)
Ответ №4:
У вас есть две проблемы в этой части кода, внутри вашей calculate
функции:
switch(randNum){
case 1:
let add = add(num1, num2)
break;
case 2:
let subtract = subtract(num1, num2);
break;
case 3:
let multiply = multiply(num1, num2);
break;
-
Вы вызываете свои математические функции (
add(num1, num2)
например) внутри calculate. Это вернет число, но ожидаемое поведение заключается в том, что оно вернет функцию, чтобы вы могли вызвать ее с дополнительными параметрами:let result = calculate(add, subtract, multiply)(1,3)
-
Ваша
calculate
функция не возвращает никакого значения. Таким образом, при выполнении ваших действийlet result = calculate(...)
результат всегда будет неопределенным.
Вместо этого ваша calculate
функция должна возвращать функцию:
function calculate(add, subtract, multiply){
let randNum = Math.floor(Math.random() * 3) 1;
switch(randNum){
case 1:
return add;
case 2:
return subtract;
case 3:
return multiply;
}
}
ДЕМОНСТРАЦИЯ:
https://jsbin.com/jiholifife/edit?js ,консоль
Обратите внимание на разницу: ваша функция calculate
теперь возвращает функцию.
Это возможно из-за того, что функции в JavaScript являются объектами первого класса: функция может быть передана в качестве аргумента другим функциям, может быть возвращена другой функцией и может быть присвоена в качестве значения переменной.