简体   繁体   English

纯函数可以返回一个随机时间后解析的承诺吗?

[英]Can a pure function return a promise that resolves after a random amount of time?

I know this example is quite contrived but I am still curious wether or not this can be considered a pure function: 我知道这个例子很做作,但我仍然很好奇或者不是这可以被认为是一个纯粹的功能:

const addAsync = (x, y) => new Promise((resolve, reject) => {
    setTimeout(
        () => resolve(x + y),
        Math.random() * 1000
    );
});

Every call to this function returns a Promise that resolves to the sum of the two arguments. 每次调用此函数都会返回一个Promise,该Promise解析为两个参数的总和。 The promise resolves after a random amount of time between 0 and 1 seconds. 承诺在0到1秒之间的随机时间后解决。

For all intends and purposes, this seems to be perfectly pure, meaning that I can treat this function in tests or in my code as a pure function (a, b) -> Promise(a + b) . 对于所有的目的和目的,这似乎是完全纯粹的,这意味着我可以在测试中或在我的代码中将此函数视为纯函数(a, b) -> Promise(a + b) However, since we are using Math.random() , we cannot transform this function into a lookup table and back without losing functionality (we lose the delay). 但是,由于我们使用的是Math.random() ,因此我们无法将此函数转换为查找表并返回而不会丢失功能(我们会丢失延迟)。 So can this considered to be pure or not? 那么这可以被认为是纯粹的吗?

I believe it can be consider as a pure function. 我相信它可以被认为是一个纯粹的功能。 A pure function is defined as a function where the return value is only determined by its input values, without observable side effects. 纯函数定义为一种函数,其中返回值仅由其输入值确定,没有可观察到的副作用。

In this case the output is only determined by its input and it doesn't produce any side effects. 在这种情况下,输出仅由其输入确定,并且不会产生任何副作用。 The fact that it takes different amount of time to compute the result should not have an effect on its pureness. 计算结果需要不同时间的事实不应影响其纯度。

But i would warn that i am not a functional programming expert and i may be wrong 但我会警告我不是函数式编程专家,我可能错了

Let's clarify the term pure first. 让我们首先澄清纯粹一词。 Purity means referential transparency, ie. 纯度意味着参考透明度,即。 one can replace an expression with its evaluated result without altering the behavior of the program. 一个人可以用其评估结果替换表达式而不改变程序的行为。 Here is an action that returns a promise. 这是一个返回承诺的动作。 To visualize the computation I perform logging as a side effect: 为了可视化计算,我执行记录作为副作用:

 const addAsync = (x, y) => new Promise((r, e) => { setTimeout( z => (console.log(z), r(z)), Math.random() * 1000, x + y ); }); console.log("before"); addAsync(2, 3); console.log("after"); // logs "before" "after" 5 

Next I substitute the expression addAsync(2, 3) with its result, which is a fulfilled Promise containing 5 . 接下来,我将表达式addAsync(2, 3)替换为其结果,该结果是包含5已实现Promise Since there is no Promise literal in Javascript, I represent an already settled promise with Promise.resolve : 由于Javascript中没有Promise文字,我用Promise.resolve表示已经解决的承诺:

 console.log("before"); Promise.resolve(console.log(5), 5); console.log("after"); // logs "before" 5 "after" 

Looking at the code there seems to be no difference. 看代码似乎没什么区别。 The expression addAsync(2, 3) yields a settled promise (kind of like Promise(5) ). 表达式addAsync(2, 3)产生一个固定的承诺(类似于Promise(5) )。 Promise.resolve(console.log(5), 5) on the other hand represents this very settled promise. Promise.resolve(console.log(5), 5)代表了这个非常稳定的承诺。 But by observing the console.log side effects we can see that the evaluation order has changed, that is a function that returns a promise actually alters the behavior of a program. 但是通过观察console.log副作用,我们可以看到评估顺序已经改变,这是一个返回promise的函数实际上改变了程序的行为。 Hence such a function is impure. 因此,这种功能是不纯的。

No. 没有。

I would argue that the state the returned Promise is in, is unknown to us, just like the life of the cat of Schroedinger . 我认为返回的诺言所处的状态对我们来说是未知的,就像施罗丁格猫生命一样。 The Promise is either resolved or rejected or pending, but we cannot predict when it is in what state. Promise要么已经解决,要么被拒绝或待决,但是我们无法预测它何时处于什么状态。 A snippet that outlines this: 一个概述了这个的片段:

 let a = 0;
 addAsync(1,2).then(res => a += res).then(console.log);
 addAsync(0, 1).then(res => a += res).then(console.log);

If addAsync would be pure, it would always log the same. 如果addAsync是纯粹的,它将始终记录相同。

Simple answer is NO. 简单的答案是否定的。 But I offer a simple way to push the impurity elsewhere 但我提供了一种简单的方法来将杂质推到别处

In the pure part of your code 在代码的纯粹部分

const incRandomDelay = addAsync.bind(null,1)

Now somewhere in the effects part of your code 现在在代码的效果部分的某个地方

incRandomDelay(10).then( sum => writeToFile(sum) )

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM