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]