Reputation: 4891
I am trying to write a bootstrap algorithm in F# that takes a collection of inputs and creates a list of outputs. If I only need to use the previous element it is straightforward to use recursion :
let buildElement head previous =
// do something to create new float
1.0
let buildList inputs =
let rec bootstrap elements previous =
let addElement head tail =
let newElement = buildElement head previous
newElement :: bootstrap tail newElement
match inputs with
| [] -> []
| h::t -> addElement h t
bootstrap inputs 1.0
However, if I want to use the previously created elements (eg say I wanted to pass in an average of the new values as the previous value), how do I access them in the inner functions? Do I create a collection in the outer function and fill it up in the inner function? If so, do I need to make it mutable?
Upvotes: 1
Views: 172
Reputation: 137947
if I want to use the previously created elements (eg say I wanted to pass in an average of the new values as the previous value), how do I access them in the inner functions?
This is a fold
or scan
(prefix fold). You're both mapping or collapsing a list into a new value, and accumulating a value that influences the result.
Upvotes: 0
Reputation: 243041
If you need to calculate the new value based on some information from the past values, you would essentially do the same thing as what you're doing now - instead of passing ingle last value in previous
, the previous
parameter could be a list of past values that you recalculate as you go.
I think it is difficult to give a better answer without knowing a specific example. However, say you wanted to calculate floating average - for that, you need the count and the sum of all previous values. You could encode that directly using recursion, or you can use Seq.scan
:
[ 1.0 .. 100.0 ]
|> Seq.scan (fun (count, sum) elem -> count + 1, sum + elem) (0, 0.0)
|> Seq.map (fun (count, sum) -> sum / float count)
Upvotes: 2
Reputation: 370112
In case of the average function you could pass the partial sum and the number of processed items around and use that calculate the average.
For a general solution, you can take the list of previous results as an argument, prepend the next result to it using ::
and reverse the whole thing when you're done. This has the added benefit of making your function tail-recursive.
Upvotes: 0