如果我们使用闭包,如何提高功能的纯度

How to enhance purity of function if we are using closures

提问人:Isaac 提问时间:9/20/2021 更新时间:9/21/2021 访问量:95

问:

我有一个伪函数,如下所示

let counter = 0;

function createNewFile() {
  const fileName = `book_${counter++}`;

  //...write file or whatever
};

上述功能绝对不理想,因为它依赖于外部变量,可能会意外更改。我正在考虑通过关闭和 IIFE 来减少这种情况发生的可能性,如下所示createNewFilecounter

const counter = (() => {
  let counter = 0;
  return () => counter++;
})();

console.log(counter())
console.log(counter())

/*
function createNewFile() {
  const fileName = `book_${counter()}`;

  //...write file or whatever
};
*/

上面的代码达到了现在可以说“更难”“意外”更改的目的。counter

但是,我想知道从函数式编程的角度来看,我们如何才能同时改进函数和?因为显然两者都违反了规则,而且两个函数在每次执行时都不提供相同的输出,所以我很好奇如何在给定用例的情况下增强代码?countercreateNewFilepure function

JavaScript 函数式编程 闭包

评论

1赞 jabaa 9/20/2021
这个问题对我来说没有意义。您希望通过使用函数状态来避免全局变量,并且希望通过闭包具有状态的纯函数。这到底意味着什么?纯函数没有状态。
3赞 Pointy 9/20/2021
对于像您这样的函数,它基本上是一个生成器,“纯度”并不是一个相关的概念。
1赞 Mark Seemann 9/20/2021
只要动作要写入文件系统,无论如何它都是不纯的,因为副作用......那么,它是否依赖于可变状态不是无关紧要吗?
0赞 VLAZ 9/20/2021
潜在的重复?在函数式编程中实现双向计数器?
1赞 Peter Seliger 9/20/2021
纯粹但无论如何最直观的方法是将计数器作为论据传递给......喜欢。。。。。。因此,程序的另一部分负责管理以及如何利用它。function createNewFile(counterValue) { /* ... */ }createNewFile(counter);countercreateNewFile

答:

1赞 user5536315 9/21/2021 #1

您的函数与两个效果有关:

  • 依赖局部变量进行突变
  • 通过写入文件系统进行 I/O

您可以通过将局部变量作为参数传递来简单地避免局部变量。状态将移动到调用堆栈。但是,使用这种技术无法避免所有突变。出于这个原因,函数式编程通常提供持久数据结构,这是一种巧妙的不变形式。

I/O 效果更难处理。在 Javascript 中,I/O 通常是异步的,因此 promise 用于对此类计算进行编码。不幸的是,从功能角度来看,promise 具有相当无原则的语义,因此我将使用原始延续类型来展示如何在后台延迟 I/O 效果:

function createNewFile(counter, data) {
  const fileName = `book_${counter}`;
  return k => {run: k(writeFile(fileName, data))}
};

const description = createNewFile(1, someData);

description.run(checkSuccess);

我们没有执行效果,而只是得到这个动作的描述。该函数本身并不是特别有用。我们需要方法将其结果应用于其他纯函数,或者将其与其他描述相结合,而无需实际执行效果,但这超出了本答案的范围。