javascript 地图函数的包装器
Wrapper for javascript map function
我有两个 javascript 函数 stack(y, f) 和 val(yi, x)。
stack(y, f) 应该表现得像
y.map(function(yi) { f } )
它 returns 一个数组 r,其中每个元素 r[i] 是数组参数 y[i] 的相应元素和作为第二个参数传递的表达式 f 的函数。
f 可以是任何计算为单个值的 javascript 代码,但是,如果它取决于函数 val,则此函数将取决于 y[i].
[r[0], r[1], ...] = stack( [y[0], y[1], ...], foo( val(y[i], x1), val(y[i], x2), ... ) )
我考虑了以下丑陋的方法,我将表达式作为字符串传递,并在循环中进行字符串替换 - 然后对其求值。
https://jsfiddle.net/zuyt954g/
function val(yi,x) {
return 10**yi+x;
}
function foo(x1,x2,x3) {
return x1+x2+x3;
}
function stack(y,f) {
return y.map(function(yi) {
return eval(f.replace(/yi/g, yi));
});
}
console.log([1,2].map(function(yi) {
return foo(val(yi,3),val(yi,4),val(yi,5))
} ))
>> [42, 312]
console.log(stack([1,2], "foo(val(yi,3),val(yi,4),val(yi,5))"))
>> [42, 312]
我想知道您是否能看到任何更简洁的解决方案,理想情况下我会避免计算字符串表达式。作为替代方案,我已经考虑过 val 返回一个数组,如果它检测到 stack 是它的远亲之一,但是获取调用堆栈和 y 似乎很重要。
any cleaner solution, where ideally I would avoid evaluating a string expression
很简单,用一个函数代替。您摆脱了非常容易出错的字符串,使您的代码更易于维护,并且更易于阅读和理解。
字符串"foo(val(yi,3),val(yi,4),val(yi,5))"
可以转化为函数:
function(yi) {
return foo(val(yi,3),val(yi,4),val(yi,5));
}
并且当被调用而不是替换字符串 yi
时,现在您可以直接传入它,所以
eval(f.replace(/yi/g, yi));
转换为简单
f(yi);
此转换的外观如下:
function val(yi, x) {
return 10 ** yi + x;
}
function foo(x1, x2, x3) {
return x1 + x2 + x3;
}
function stack(y, f) {
return y.map(function(yi) {
return f(yi);
})
}
console.log([1, 2].map(function(yi) {
return foo(val(yi, 3), val(yi, 4), val(yi, 5))
}))
//>> [42, 312]
console.log(stack([1, 2], function(yi) {
return foo(val(yi, 3), val(yi, 4), val(yi, 5))
}))
//>> [42, 312]
不过,现在我们可以稍微改进一下。这里有一点冗余:
return y.map(function(yi) {
return f(yi);
})
map
收到一个回调,它接受一个参数并调用另一个也接受相同参数的函数。这两个函数都有 arity of 1 the only purpose of the anonymous callback is to forward the parameter to f
. Therefore, calling the anonymous callback with yi
is the same as calling f(yi)
. We can remove this "empty wrapper" by what in Lambda Calculus is called Eta reduction,因为 f
与回调 完全 相同。在我们的例子中,这意味着 stack
变成:
function stack(y, f) {
return y.map(f)
}
最后一点,我们可以通过重新使用函数来进一步证明相等性
function(yi) {
return foo(val(yi, 3), val(yi, 4), val(yi, 5))
}
现在存在两次:
function val(yi, x) {
return 10 ** yi + x;
}
function foo(x1, x2, x3) {
return x1 + x2 + x3;
}
function stack(y, f) {
return y.map(f);
}
function testFunction(yi) { // ---|
return foo(val(yi, 3), val(yi, 4), val(yi, 5)); // |->-
} // ---| |
// v
// |
console.log([1, 2].map(testFunction)) //<-----------------<--
//>> [42, 312] |
// v
// |
console.log(stack([1, 2], testFunction)) //<--------------<--
//>> [42, 312]
我有两个 javascript 函数 stack(y, f) 和 val(yi, x)。
stack(y, f) 应该表现得像
y.map(function(yi) { f } )
它 returns 一个数组 r,其中每个元素 r[i] 是数组参数 y[i] 的相应元素和作为第二个参数传递的表达式 f 的函数。
f 可以是任何计算为单个值的 javascript 代码,但是,如果它取决于函数 val,则此函数将取决于 y[i].
[r[0], r[1], ...] = stack( [y[0], y[1], ...], foo( val(y[i], x1), val(y[i], x2), ... ) )
我考虑了以下丑陋的方法,我将表达式作为字符串传递,并在循环中进行字符串替换 - 然后对其求值。 https://jsfiddle.net/zuyt954g/
function val(yi,x) {
return 10**yi+x;
}
function foo(x1,x2,x3) {
return x1+x2+x3;
}
function stack(y,f) {
return y.map(function(yi) {
return eval(f.replace(/yi/g, yi));
});
}
console.log([1,2].map(function(yi) {
return foo(val(yi,3),val(yi,4),val(yi,5))
} ))
>> [42, 312]
console.log(stack([1,2], "foo(val(yi,3),val(yi,4),val(yi,5))"))
>> [42, 312]
我想知道您是否能看到任何更简洁的解决方案,理想情况下我会避免计算字符串表达式。作为替代方案,我已经考虑过 val 返回一个数组,如果它检测到 stack 是它的远亲之一,但是获取调用堆栈和 y 似乎很重要。
any cleaner solution, where ideally I would avoid evaluating a string expression
很简单,用一个函数代替。您摆脱了非常容易出错的字符串,使您的代码更易于维护,并且更易于阅读和理解。
字符串"foo(val(yi,3),val(yi,4),val(yi,5))"
可以转化为函数:
function(yi) {
return foo(val(yi,3),val(yi,4),val(yi,5));
}
并且当被调用而不是替换字符串 yi
时,现在您可以直接传入它,所以
eval(f.replace(/yi/g, yi));
转换为简单
f(yi);
此转换的外观如下:
function val(yi, x) {
return 10 ** yi + x;
}
function foo(x1, x2, x3) {
return x1 + x2 + x3;
}
function stack(y, f) {
return y.map(function(yi) {
return f(yi);
})
}
console.log([1, 2].map(function(yi) {
return foo(val(yi, 3), val(yi, 4), val(yi, 5))
}))
//>> [42, 312]
console.log(stack([1, 2], function(yi) {
return foo(val(yi, 3), val(yi, 4), val(yi, 5))
}))
//>> [42, 312]
不过,现在我们可以稍微改进一下。这里有一点冗余:
return y.map(function(yi) {
return f(yi);
})
map
收到一个回调,它接受一个参数并调用另一个也接受相同参数的函数。这两个函数都有 arity of 1 the only purpose of the anonymous callback is to forward the parameter to f
. Therefore, calling the anonymous callback with yi
is the same as calling f(yi)
. We can remove this "empty wrapper" by what in Lambda Calculus is called Eta reduction,因为 f
与回调 完全 相同。在我们的例子中,这意味着 stack
变成:
function stack(y, f) {
return y.map(f)
}
最后一点,我们可以通过重新使用函数来进一步证明相等性
function(yi) {
return foo(val(yi, 3), val(yi, 4), val(yi, 5))
}
现在存在两次:
function val(yi, x) {
return 10 ** yi + x;
}
function foo(x1, x2, x3) {
return x1 + x2 + x3;
}
function stack(y, f) {
return y.map(f);
}
function testFunction(yi) { // ---|
return foo(val(yi, 3), val(yi, 4), val(yi, 5)); // |->-
} // ---| |
// v
// |
console.log([1, 2].map(testFunction)) //<-----------------<--
//>> [42, 312] |
// v
// |
console.log(stack([1, 2], testFunction)) //<--------------<--
//>> [42, 312]