Curried函数:如何优化它们

时间:2016-12-07 15:03:55

标签: functional-programming ramda.js

我对函数式编程和ramda.js这样的库比较陌生,但我觉得非常有用的一件事就是可以理解函数。

使用curried函数我经常写下以下内容

const myFun = R.curry(
  (arg1, arg2) => {
    let calculated = anotherFun(arg1)
      //do something with calculated and arg2
    return calculated * 5 + arg2
  }
)

const anotherFun = (arg) => {
  console.log("calling anotherFun");
  return arg + 1
}

var partial = myFun(1)

console.log(partial(2))
console.log(partial(3))
<script src="//cdn.jsdelivr.net/ramda/0.22.1/ramda.min.js"></script>

但显然在这种情况下anotherFun每次拨打partial时都会被呼叫,即使在arg1中也是如此,因此calculated始终是相同的。

有没有办法优化此行为并仅在其args更改时调用anotherFun

我想到的唯一方法就是这个

const myFun = R.curry(
  (calculated, arg2) => {
    return calculated * 5 + arg2
  }
)

const anotherFun = (arg) => {
  console.log("calling anotherFun");
  return arg + 1
}

var calculated = anotherFun(1)
var partial = myFun(calculated)

console.log(partial(2))
console.log(partial(3))
<script src="//cdn.jsdelivr.net/ramda/0.22.1/ramda.min.js"></script>

但是这样我必须更改传递给myFun的参数,这会使外部API复杂化

3 个答案:

答案 0 :(得分:3)

如果您像这样手动进行晃动

const myFun = arg1 => arg2 => {
  let calculated = anotherFun(arg1)
  // do something with calculated and arg2
  return calculated * 5 + arg2
};

您也可以进行此优化:

const myFun = arg1 => {
  let calculated = anotherFun(arg1);
  return arg2 => {
    // do something with calculated and arg2
    return calculated * 5 + arg2
  };
};

我不认为拉姆达会在这里帮助你;并且JavaScript编译器当然不会进行这种优化。

答案 1 :(得分:1)

@Bergi是对的,Ramda不会为你提供任何帮助。如果你想要一个Ramda风格的结果,你可以用一个参数来调用函数来获取函数,或者两者都可以得到结果,你可以这样做:

const myFun = function(arg1, arg2) {
  let calculated = anotherFun(arg1);
  const newFunc = arg2 => {
    return calculated * 5 + arg2
  };
  return (arguments.length < 2) ? newFunc : newFunc(arg2);
};

const with3 = myFun(3);
//: calling anotherFun

with3(1); //=> 21
with3(2); //=> 22
with3(4); //=> 23


myFun(2, 7);
//: calling anotherFun
//=> 22 

myFun(2, 8);
//: calling anotherFun
//=> 23 

这是以无法使用ES2015箭头功能为代价的。但它对你来说可能是值得的。

如果提供了两个参数,如果这对您很重要,您也可以稍微重做这一点,以便不构建内部函数。

答案 2 :(得分:0)

Ramda的useWithmemoize怎么样?

const myFun = R.useWith(
  (a, b) => a * 5 + b,
  [R.memoize(anotherFun), R.identity]
);