我知道IO用于将纯代码与不纯代码分开。此外,我知道IO允许参考透明度。
关于IO的一件事虽然对我来说仍然有点模糊。也就是说,保证IO包含的动作之间没有任何不好可能发生,因为它在调用时一次全部运行(因为它只不过是一个懒惰的组合)。因此,当最终调用这个惰性组合时,没有其他并发代码可以扭曲(这个懒惰的组合)。
那是真的吗? IO会比这样的代码更好(在这种情况下)吗?var x = 1; //shared resource
//some other code access and changes x to 2
const y = multiplyBy100(x);
const z = add1000(y);
log(z); // 1200 instead of desired 1100
我知道IO是解决这个问题的方法。
IO(function () {return x;}).map(multiplyBy100).map(add1000).map(log); //1100 no matter what
我的推理好吗?
答案 0 :(得分:0)
你的思维从正确的方向开始,因为IO monads允许分离不纯和纯粹的行为。当你提到
时,我认为你错过了一些东西另外,我知道IO允许参考透明度。
您可能会将IO本身的语义与它们之外的代码所带来的好处混为一谈。 IO本身并不允许引用透明性,而是允许引用透明(纯)的函数与IO中包含的不纯行为进行交互,而不会丢失其引用透明性。
当您撰写IO动作并运行它时,结果不保证是引用透明的,这正是重点。当我们理解IO是不纯行为的倾销地时,这并不奇怪。
所以,当这个懒惰的组合最终被调用时,没有其他并发 代码可以扭曲(这种懒惰的构图)。
不幸的是,它并不那么简单。懒惰的代码不会使它在引用上透明。对一系列函数(例如IO被延迟(懒惰))的评估与它们运行的值无关。
在javascript的上下文中,所有值都是引用。堆栈上的任何函数(在其范围内,引用)都可以更改所述引用的值。让我向您展示这对您自己的示例代码意味着什么,显示IO无论如何都返回1100的值。当我在声明IO包装x之前或之后更改x的值时,IO返回的值将反映这样的更改。因此,此代码不会返回//1100 no matter what
,但实际上会返回1200
。
function switcharoo() {
x = 2;
}
var x = 1;
var IOdoMaths = IO(() => x).map(x => x * 100).map(x => x + 1000);
// Some concurrent proccess calls this
switcharoo();
var result = IOdoMaths.runIO();
console.log(result); // 1200
我们期待IO操作导致1100
,但我们得到1200
。请记住,当我们创建IO时,我们包含了引用而不是值。这适用于Javascript中的任何类型的闭包。如果在声明后在IO中填充闭包并不重要,则适用相同的规则。