Can a pure function return a promise that resolves after a random time?

I know this example is quite inventive, but I'm still curious or not, this can be considered a pure function:

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

Each call to this function returns a promise that resolves the sum of the two arguments. A promise is resolved after a random period of time between 0 and 1 second.

For all purposes, it seems completely clean, which means that I can consider this function in tests or in my code as a pure function (a, b) -> Promise(a + b) . However, since we use Math.random() , we cannot convert this function to the lookup table and vice versa without losing functionality (we lose the delay). So can it be considered clean or not?

+5
source share
4 answers

I believe that this can be considered as a pure function. A pure function is defined as a function where the return value is determined only by its input values ​​without visible side effects.

In this case, the output is determined only by its input and does not cause any side effects. The fact that a different amount of time is required to calculate the result should not affect its purity.

But I would warn that I am not a specialist in functional programming, and I may be wrong

+3
source

Let me first clarify the term clean. Cleanliness means referential transparency, i.e. You can replace the expression with the estimated result without changing the behavior of the program. Here is the action that returns the promise. To visualize the calculation, I am recording 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 

Then I substitute the expression addAsync(2, 3) with my result, which is a Promise that contains 5 . Since there is no Promise literal in Javascript, I present an already established promise with 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 addAsync(2, 3) expression gives an established promise (sort of like Promise(5) ). Promise.resolve(console.log(5), 5) , on the other hand, represents this very long promise. But, observing the side effects of console.log , we see that the evaluation order has changed, that is, the function that returns the promise actually changes the behavior of the program. Therefore, such a function is unclean.

+2
source

No.

I would say that the state in which the promise was returned is unknown to us, like the life of the Schrödinger cat . A promise is either allowed, rejected, or not expected, but we cannot predict when it is in what condition. The trim that describes 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 is clean, it will always write the same thing.

+1
source

The simple answer is NO. But I suggest an easy way to push the admixture elsewhere

In the clean part of your code

 const incRandomDelay = addAsync.bind(null,1) 

Now somewhere in the part of the effects of your code

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

Source: https://habr.com/ru/post/1275569/


All Articles