根据输入参数动态生成 JavaScript 中的函数
Dynamically generate a function in JavaScript depending on input parameters
我有一个成本函数,它应该根据用户和对象的参数输出成本。
作为一个简单但不现实的例子,让我们考虑:
// example of input user
let user1 = {
access: [true, false],
utility: [2, 5]
};
// example of input object
let object1 = {type: 0, cost: 15};
// static vertions of the cost function
const costFunction = (user, object) => {
switch (object.type){
case 0:
if(user.access[0]){
return object.cost * user.utility[0];
}else{
return Infinity;
};
case 1:
if(user.access[1]){
return object.cost * user.utility[1];
}else{
return Infinity;
};
};
};
costFunction(user1, object1) // sould return 2*15 = 30
但是,在一个算法中,我必须针对同一用户但针对不同的对象多次调用此函数。所以,我希望能够只处理一次用户的参数,并动态生成一个用户适应的成本函数,如下所示:
// dynamically generated a user-adapted const function
const costFunctionGenerator = (user) => {
... some code ...
const costFunction = (object) => {
... some code ...
};
return costFunction;
};
const user1CostFunction = costFunctionGenerator(user1)
这样,user1CostFunction
就等于
const user1CostFunction = (object) => {
switch (object.type){
case 0:
return object.cost * 2;
case 1:
return Infinity;
}
}
发生的事情是我们删除了来自用户参数的 if
条件 user1.access
并且我们还将链接从 user1.utility
转换为 [=14= 中的直接浮动元素].
我的问题是我不知道如何实现功能costFunctionGenerator
。
您要查找的模式名称称为柯里化函数。
在 es6 之前的 Javascript 中,创建柯里化函数有点笨拙,但是随着箭头函数的出现,语法变得更好了。基本上,您唯一需要做的就是将您的签名更改为:
const costFunctionCurried = (user) => (object) => {
switch (object.type){
case 0:
if(user.access[0]){
return object.cost * user.utility[0];
}else{
return Infinity;
};
case 1:
if(user.access[1]){
return object.cost * user.utility[1];
}else{
return Infinity;
};
};
};
但是它是如何工作的呢?当您第一次调用 costFunctionCurried
时,它会 修复
所有调用变量 user 和 returns 新 lambda 的地方,它只需要传递对象:
costFunctionCurried(user1)(object1) //you can call it inline
//or you can assign your function to a variable for reuse
const fixedUserCostFunction = costFunctionCurried(user1)
fixedUserCostFunction(object1)
fixedUserCostFunction(object2) //etc.
我创建了一个 benchmark 来测试柯里化版本是否提供任何性能优势并且确实执行得更快。
我有一个成本函数,它应该根据用户和对象的参数输出成本。 作为一个简单但不现实的例子,让我们考虑:
// example of input user
let user1 = {
access: [true, false],
utility: [2, 5]
};
// example of input object
let object1 = {type: 0, cost: 15};
// static vertions of the cost function
const costFunction = (user, object) => {
switch (object.type){
case 0:
if(user.access[0]){
return object.cost * user.utility[0];
}else{
return Infinity;
};
case 1:
if(user.access[1]){
return object.cost * user.utility[1];
}else{
return Infinity;
};
};
};
costFunction(user1, object1) // sould return 2*15 = 30
但是,在一个算法中,我必须针对同一用户但针对不同的对象多次调用此函数。所以,我希望能够只处理一次用户的参数,并动态生成一个用户适应的成本函数,如下所示:
// dynamically generated a user-adapted const function
const costFunctionGenerator = (user) => {
... some code ...
const costFunction = (object) => {
... some code ...
};
return costFunction;
};
const user1CostFunction = costFunctionGenerator(user1)
这样,user1CostFunction
就等于
const user1CostFunction = (object) => {
switch (object.type){
case 0:
return object.cost * 2;
case 1:
return Infinity;
}
}
发生的事情是我们删除了来自用户参数的 if
条件 user1.access
并且我们还将链接从 user1.utility
转换为 [=14= 中的直接浮动元素].
我的问题是我不知道如何实现功能costFunctionGenerator
。
您要查找的模式名称称为柯里化函数。
在 es6 之前的 Javascript 中,创建柯里化函数有点笨拙,但是随着箭头函数的出现,语法变得更好了。基本上,您唯一需要做的就是将您的签名更改为:
const costFunctionCurried = (user) => (object) => {
switch (object.type){
case 0:
if(user.access[0]){
return object.cost * user.utility[0];
}else{
return Infinity;
};
case 1:
if(user.access[1]){
return object.cost * user.utility[1];
}else{
return Infinity;
};
};
};
但是它是如何工作的呢?当您第一次调用 costFunctionCurried
时,它会 修复
所有调用变量 user 和 returns 新 lambda 的地方,它只需要传递对象:
costFunctionCurried(user1)(object1) //you can call it inline
//or you can assign your function to a variable for reuse
const fixedUserCostFunction = costFunctionCurried(user1)
fixedUserCostFunction(object1)
fixedUserCostFunction(object2) //etc.
我创建了一个 benchmark 来测试柯里化版本是否提供任何性能优势并且确实执行得更快。