Ответ 1
Не уверен, что понял, что ты хочешь, но
function sum(n) {
var v = function(x) {
return sum(n + x);
};
v.valueOf = v.toString = function() {
return n;
};
return v;
}
console.log(+sum(1)(2)(3)(4));
Мне нужна функция js sum для работы следующим образом:
sum(1)(2) = 3
sum(1)(2)(3) = 6
sum(1)(2)(3)(4) = 10
etc.
Я слышал, что это невозможно. Но слышал, что если добавить +
перед sum
, можно сделать.
Как +sum(1)(2)(3)(4)
.
Любые идеи о том, как это сделать?
Не уверен, что понял, что ты хочешь, но
function sum(n) {
var v = function(x) {
return sum(n + x);
};
v.valueOf = v.toString = function() {
return n;
};
return v;
}
console.log(+sum(1)(2)(3)(4));
Это пример использования пустых скобок в последнем вызове в качестве закрытого ключа (из моего последнего интервью):
сумма (1) (4) (66) (35) (3)()
function sum(numberOne) {
var count = numberOne;
return function by(numberTwo) {
if (numberTwo === undefined) {
return count;
} else {
count += numberTwo;
return by;
}
}
}
console.log(sum(1)(4)(66)(35)(3)());
Я публикую эту ревизию как свой собственный пост, так как у меня, видимо, недостаточно репутации, чтобы просто оставить ее в качестве комментария. Это пересмотр превосходного решения @Rafael.
function sum (n) {
var v = x => sum (n + x);
v.valueOf = () => n;
return v;
}
console.log(+sum(1)(2)(3)(4)); //10
Я не видел причины держать бит v.toString, поскольку это не казалось необходимым. Если я ошибаюсь при этом, сообщите мне в комментариях, почему требуется v.toString(он прошел мои тесты отлично без него). Преобразование остальных анонимных функций в функции стрелок для удобства чтения.
Вы можете использовать следующую функцию
function add(num){
add.sum || (add.sum = 0) // make sure add.sum exists if not assign it to 0
add.sum += num; // increment it
return add.toString = add.valueOf = function(){
var rtn = add.sum; // we save the value
return add.sum = 0, rtn // return it before we reset add.sum to 0
}, add; // return the function
}
Так как функции являются объектами, мы можем добавлять к ним свойства, которые мы возвращаем, когда они были доступны.
Вот решение, которое использует ES6 и toString
, подобно @Vemba
function add(a) {
let curry = (b) => {
a += b
return curry
}
curry.toString = () => a
return curry
}
console.log(add(1))
console.log(add(1)(2))
console.log(add(1)(2)(3))
console.log(add(1)(2)(3)(4))
Чтобы сделать sum(1)
вызываемым как sum(1)(2)
, он должен вернуть функцию.
Функция может быть вызвана или преобразована в число с помощью valueOf
.
function sum(a) {
var sum = a;
function f(b) {
sum += b;
return f;
}
f.toString = function() { return sum }
return f
}
Так как это общий вопрос для интервью, здесь я беру с использованием свойств функции, чтобы добавить memoization в функцию sum() и немного упростить его код:
function sum(x) {
sum.result = (sum.result) ? sum.result += x : x;
sum.valueOf = function() {
return sum.result;
}
return sum;
}
sum(1)(2)(3); // == 6
Другой немного более короткий подход:
const sum = a => b => b? sum(a + b) : a;
Используется как:
console.log(
sum(1)(2)(),
sum(3)(4)(5)()
);
Вот решение с универсальной функцией variadic curry в ES6 Javascript, с оговоркой, что final ()
необходим для вызова аргументов:
const curry = (f) =>
(...args) => args.length? curry(f.bind(0, ...args)): f();
const sum = (...values) => values.reduce((total, current) => total + current, 0)
curry(sum)(2)(2)(1)() == 5 // true
Вот еще один, который не нуждается ()
, используя valueOf
как в ответе @rafael. Я чувствую, что использование valueOf
таким образом (или, возможно, вообще) очень сбивает с толку людей, читающих ваш код, но каждый по-своему.
toString
в этом ответе не требуется. Внутренне, когда javascript выполняет приведение типов, он всегда вызывает valueOf()
перед вызовом toString()
.
// invokes a function if it is used as a value
const autoInvoke = (f) => Object.assign(f, { valueOf: f } );
const curry = autoInvoke((f) =>
(...args) => args.length? autoInvoke(curry(f.bind(0, ...args))): f());
const sum = (...values) => values.reduce((total, current) => total + current, 0)
curry(sum)(2)(2)(1) + 0 == 5 // true
Может быть старый вопрос, но немного расширенный ответ
function sum() {
var args = [];
args.push(...arguments);
function sumOfAllArguments() {
return args.reduce((prev,items)=>prev + items, 0)
}
function v() {
arguments && args.push(...arguments);
return arguments.length === 0 ? sumOfAllArguments() : v;
}
v.valueOf = v.toString = sumOfAllArguments;
return v;
}
console.log(sum(2)(2)(2)()) // 6
console.log(sum(2)(2)(2).toString()) // 6
console.log(sum(2)(2)(2).valueOf()) // 6
console.log(+sum(2)(2)(2)) //6
console.log(sum(2)(2)(2)) // f 6
console.log(sum(2,2,2)(2,2)(2)) // f 12
console.log(sum(2)(2,2)(2)()) // 8
function sum(a){
let res = 0;
function getarrSum(arr){
return arr.reduce( (e, sum=0) => { sum += e ; return sum ;} )
}
function calculateSumPerArgument(arguments){
let res = 0;
if(arguments.length >0){
for ( let i = 0 ; i < arguments.length ; i++){
if(Array.isArray(arguments[i])){
res += getarrSum( arguments[i]);
}
else{
res += arguments[i];
}
}
}
return res;
}
res += calculateSumPerArgument(arguments);
return function f(b){
if(b == undefined){
return res;
}
else{
res += calculateSumPerArgument(arguments);
return f;
}
}
}
let add = (a) => {
let sum = a;
funct = function(b) {
sum += b;
return funct;
};
Object.defineProperty(funct, 'valueOf', {
value: function() {
return sum;
}
});
return funct;
};
console.log(+add(1)(2)(3))
Вот еще один функциональный способ использования итеративного процесса
const sum = (num, acc = 0) => {
if (!num) return acc;
return x => sum(x, acc + num)
}
sum(1)(2)(3)()
и однострочный
const sum = (num, acc = 0) => !num ? acc : x => sum(x, acc + num)
sum(1)(2)(3)()