In my previous article I derived the calculation for passive income from invested assets and demonstrated a small calculator. It struck me that there was a slight delay in the case of high annual numbers. The cause of the delay lies in my implementation of the formula $$ \sum_{k = 1}^{m-1} \frac {1} {\prod_ {t = 1} ^ {k} w_t}. $$
As described in more detail in the article mentioned above, $ w_t $ denotes the relative market value in the month $ t $ and $ m $ the total number of months.
This article was written in German and translated to English in collaboration between man and machine.
As a beginner in functional programming, I have mainly used map
, filter
and reduce
. In order to implement the formula with the functions just mentioned in the functional language Elm, I have re-calculated the product in the denominator for each summand, such as can be seen from line 4 of the following snippet.
nMonths = List.length relativePrices
inversePartialProduct k =
1 / (List.take k relativePrices |> List.product)
inverseProducts =
List.map
inversePartialProduct
(List.range 1 (nMonths - 1))
To experience the delay, the willing reader is encouraged to enter 399 as the number of years in the following version of the tool.
The runtime complexity is therefore unnecessarily quadratic. In imperative programming, I would have cached the denominator from the previous summand in a variable. The variable could then mutate for the current summand by multiplying it by the relevant relative market value to the correct denominator *Mutations and mutants in the biological context, as we know them as the Corona-tormented generation from the media, imply a random change. However, when changing the value of a variable one speaks of mutability in programming. The change, even if it is permitted, does not have to be random.. Such changes of state are not possible in functional programming. States are always constant. Fortunately, there is a twice functional answer to my problem. In the search engine of my distrust I looked for the calculation of sequences of partial sums in functional programming. As a result, I stumbled across the function scanl
from the functional programming language Haskell. This maps a list of partial reductions. That means, with scanl
one can efficiently*Since `scanl` is a function of the standard library, I have assumed that it is efficiently implemented. implement $$ (w_t) _ {t = 1}^m \mapsto (\prod_ {k = 1} ^ t w_t) _ {t = 1}^m.$$ Yes! Why does Elm’s standard library not provide such a function? It turns out that also Elm provided this feature earlier, but strangely enough it has been banned . Fortunately, there is an implementation of scanl
in the Elm library List.Extra. The new snippet
nMonths = List.length relativePrices
inverseProducts =
List.take (nMonths - 1) relativePrices
|> List.Extra.scanl1 (*)
|> List.map (\ partialProduct -> 1 / partialProduct)
is much more efficient, which indicates a good implementation of scanl
*We call `scanl1` here, which in contrast to `scanl` performs the reductions without an extra start value. But scanl1 for its part probably uses the more general `scanl`. with linear runtime in the library List.Extra
. You can find the calculator on anextra page and the code on Github.