JavaScript和Haskell的函数组合

时间:2021-04-26 17:03:03

In JavaScript we can define function composition as using a function which takes two functions f and g, to produce a new function:

在JavaScript中,我们可以将函数组合定义为使用函数f和g两个函数生成一个新函数:

function o(f, g) {
  return function(x) {
   return f(g(x));
  }
 }

This seems obvious, but my question is, does the runtime interpreter/compiler actually calculate f(g(x))?

这似乎很明显,但我的问题是,运行时解释器/编译器是否实际计算f(g(x))?

Say we have some large data like an array with many elements, and is the previously composed function o as the f(g(x)) by the prior calculation faster than uncomposed f(g(x)) ?

假设我们有一些大数据,比如一个包含许多元素的数组,而先前组合的函数o作为f(g(x),是否比未组合的f(g(x)更快?

Perhaps, in this case, o(f, g) as merely a macro expression of f(g(x))?

或许,在这种情况下,o(f, g)仅仅是f(g(x))的宏观表达式?

And if it's a macro, perhaps, the performance doesn't make much difference?

如果它是一个宏,也许,性能没有多大差别?

It may depends on the runtime environment, I especially interested in V8 engine for Chrome/node.js.

这可能取决于运行时环境,我对Chrome/node.js的V8引擎特别感兴趣。

Haskell as a language of lazy evaluation strategy theoretically compose functions, am I correct? Does GHC actually calculate to compose functions?

Haskell作为一种惰性评价策略的语言,从理论上构建函数,对吗?GHC真的计算组成函数吗?

2 个解决方案

#1


3  

No, the function call o(f, g) will return exactly the anonymous function:

不,函数调用o(f, g)将返回匿名函数:

function (x) {
    return f(g(x));
}

Then, only at the time, when you call that anonymous function, g(x) will execute and then f will execute on the result of g(x). Every time you call that anonymous function both g and f execute, one after the other. So the using the composed function will be just a little slower than manually calling f(g(x)) everywhere in your code due to the slight overhead of the extra anonymous function.

然后,只有在调用匿名函数时,g(x)将执行,然后f将执行g(x)的结果。每次你调用匿名函数g和f都执行,一个接一个。因此,使用组合函数将比在代码中的任何地方手动调用f(g(x)稍微慢一点,因为额外的匿名函数的开销很小。

Example:

例子:

function o(f, g){
    return function(x) {
        return f(g(x));
    }
}

function addTo5(x){
    return x + 5;
}

function multiplyBy(x){
    return function(y){
        return x*y;
    }
}

var composed = o(multiplyBy, addTo5);
composed(5)(3); // Slightly slower than multiplyBy(addTo5(5))(3)

jsperf

#2


1  

No calculation is performed until you call the composed function returned by o. This new function just keeps track of what f and g are, and invoke them when you pass x in, evaluating and returning the final result.

在调用o返回的组合函数之前,不执行任何计算。这个新函数只跟踪f和g是什么,并在传入x时调用它们,计算并返回最终结果。

#1


3  

No, the function call o(f, g) will return exactly the anonymous function:

不,函数调用o(f, g)将返回匿名函数:

function (x) {
    return f(g(x));
}

Then, only at the time, when you call that anonymous function, g(x) will execute and then f will execute on the result of g(x). Every time you call that anonymous function both g and f execute, one after the other. So the using the composed function will be just a little slower than manually calling f(g(x)) everywhere in your code due to the slight overhead of the extra anonymous function.

然后,只有在调用匿名函数时,g(x)将执行,然后f将执行g(x)的结果。每次你调用匿名函数g和f都执行,一个接一个。因此,使用组合函数将比在代码中的任何地方手动调用f(g(x)稍微慢一点,因为额外的匿名函数的开销很小。

Example:

例子:

function o(f, g){
    return function(x) {
        return f(g(x));
    }
}

function addTo5(x){
    return x + 5;
}

function multiplyBy(x){
    return function(y){
        return x*y;
    }
}

var composed = o(multiplyBy, addTo5);
composed(5)(3); // Slightly slower than multiplyBy(addTo5(5))(3)

jsperf

#2


1  

No calculation is performed until you call the composed function returned by o. This new function just keeps track of what f and g are, and invoke them when you pass x in, evaluating and returning the final result.

在调用o返回的组合函数之前,不执行任何计算。这个新函数只跟踪f和g是什么,并在传入x时调用它们,计算并返回最终结果。