Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I refactor out the required else clause?

Tags:

c#

f#

I have a C# method that looks a bit like this:

bool Eval() {
  // do some work
  if (conditionA) {
     // do some work
     if (conditionB) {
       // do some work
       if (conditionC) {
         // do some work
         return true;
       }
     }
  }
  return false;
}

In F# this ends up looking quite a bit uglier because of the mandatory else branches:

let eval() =
  // do some work
  if conditionA then
    // do some work
    if conditionB then
      // do some work
      if conditionC then
        // do some work
        true
      else
        false
    else
      false
  else
    false

What would be a cleaner way of writing this in F#?

like image 812
Asik Avatar asked Aug 15 '12 20:08

Asik


2 Answers

module Condition =
  type ConditionBuilder() =
    member x.Bind(v, f) = if v then f() else false
    member x.Return(v) = v
  let condition = ConditionBuilder()

open Condition

let eval() =
  condition {
    // do some work
    do! conditionA
    // do some work
    do! conditionB
    // do some work
    do! conditionC
    return true
  }
like image 198
Daniel Avatar answered Sep 24 '22 12:09

Daniel


As mentioned in the comments, you could inverse the condition. This simplifies the C# code, because you can write:

if (!conditionA) return false;
// do some work

Although F# does not have imperative returns (if you want to return, you need both true and false branches), it actually simplifies this code a bit too, because you can write:

let eval() = 
  // do some work 
  if not conditionA then false else
  // do some work 
  if not conditionB then false else
  // do some work 
  if not conditionC then false else
    // do some work 
    true 

You still have to write false multiple times, but at least you don't have to indent your code too far. There is an unlimited number of complex solutions, but this is probably the simplest option. As for more complex solution, you could use an F# computation expression that allows using imperative-style returns. This is similar to Daniel's computation, but a bit more powerful.

like image 38
Tomas Petricek Avatar answered Sep 24 '22 12:09

Tomas Petricek