Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# - Turn simple for loop into more functional construct

I have this simple "Investment" type with a "lifetime" property:

type Investment = {
PurchasePayment: float;
Lifetime: float;
TaxWriteoff: float;
ResidualValue: float;
}

let CoffeMachine = {
    PurchasePayment = 13000.0;
    Lifetime = 4.0;
    TaxWriteoff = 2000.0;
    ResidualValue = 500.0;
}

I would like to iterate over the years of investment and perform some calculations for each year:

for i = 1 to int CoffeMachine.Lifetime do
    printf "%i" i
    // doSomething

Is there a way to avoid using for loop for that and write it in a more functional style?

Cheers,

Wojtek

like image 789
Wojciech Kulma Avatar asked Jun 04 '17 17:06

Wojciech Kulma


1 Answers

The go-to method of performing calculations on every item in a list is called map. Specifically, for your case, you can create a list of numbers from 1 to Lifetime and then use List.map to perform a calculation on each:

let calculation year = year * 2 // substitute your calculation here

let calcResults = [1..int CoffeMachine.Lifetime] |> List.map calculation

That said, I think you're confusing "functional" with "hard to understand" (or, perhaps, "show off"). The point of "functional programming" is not to be all mathematics and inaccessible to the uninitiate. The point of "functional programming" is "programming with functions". There are some practical implications of that, such as "immutable data" and "no side effects", and as long as your program satisfies those, you can consider it "functional", however simple it may look. In fact, I would argue that the simpler it looks, the better. Software maintainability is a very worthy goal.

In particular, if you just wanted to print out the years, then your code is fine: printing out itself is a "side effect", so as long as that's a requirement, there is no way to make it more "functional". But if your goal is to perform some calculation (as in my example above), then that could be expressed cleaner with a list comprehension:

let calcResults = [for year in 1..int CoffeMachine.Lifetime -> calculation year]
like image 178
Fyodor Soikin Avatar answered Oct 18 '22 23:10

Fyodor Soikin