Calculating PI using streams, head & tail in DataWeave
Thanks to [head ~ tail]
in DataWeave 2.0 we can easily create infinite
sequence generators.
In this case we are implementing the Leibniz's series to calculate an approximation of PI.
/**
* This function returns a stream. We first populate the stream with a
* head value, and a lazy tail.
* In this case, we tell the engine the tail is a function call.
* That function call will be not be executed UNTIL the value of that
* call is needed.
*/
fun leibnizTerm(n: Number = 0): Array<Number> =
[4 / (n + 1) - 4 / (n + 3) ~ leibnizTerm(n + 4)]
// ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^
// head lazy tail
/**
* Now we have the sequence generator, the only thing left is select
* the values and aggregate them. We are going to pick a slice of the
* infinite sequence of leibnizTerm using a range selector.
*/
fun pi(terms: Number = 1E4): Number = do {
var seriesSubset = leibnizTerm()[0 to terms]
// ^^^^^^^^^^^ ^^^^^^^^^^^^
// series gen range selector
---
sum( seriesSubset )
}
---
// Then executing
pi(1E4)
// Outputs: 3.1415426585893202