Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Something similar to yield break in F#

Tags:

f#

How to break after first if?

let WithdrawalCash (account, amount) = seq {        

    if ( account.Balance.CurrentAmount - amount < 0.0m) then
        yield NotEnoughMoneyForWithdrawal(account, amount)   
        // How to break here?     

    let newBalance = account.Balance.CurrentAmount - amount
    yield CashWithdrawnEvent(account, newBalance)
}
like image 296
Mike Chaliy Avatar asked Jan 02 '10 16:01

Mike Chaliy


2 Answers

Not sure this will help, why not use the else clause?

let WithdrawalCash (account, amount) = seq {        

   if ( account.Balance.CurrentAmount - amount < 0.0m) then
       yield NotEnoughMoneyForWithdrawal(account, amount)   
       // How to break here?     
   else 
      let newBalance = account.Balance.CurrentAmount - amount
      yield CashWithdrawnEvent(account, newBalance) 
}

Also have a look at:

Imperative computation in F# (II.) - Writing break and continue

like image 161
primodemus Avatar answered Oct 24 '22 02:10

primodemus


The code as posted will only evern return one CashWithdrawlEvent, then end the sequence... you need to have a loop to return multiple values. Also, have you considered using "match" to handle multiple cases?

(not tested as working...)

let WithdrawalCash (account, amount) = seq {         

    let bDone = ref false

    while not (!bDone) do
        match amount with
        | v when account.Balance.CurrentAmount - v < 0 ->
           yield NotEnoughMoneyForWithdrawal(account, amount)
           bDone := true    // break

        // more when clauses can go here

        | _ ->
          let newBalance = account.Balance.CurrentAmount - amount 
          yield CashWithdrawnEvent(account, newBalance) 
          // let the sequence continue

}

But, even this does not seem like what you would want, since it will ALWAYS withdraw the same 'amount' each time you pull a value from the sequence, because account and amount are fixed when the sequence is created. So, I'd drop the 'seq' and make this a simple function, as in:

let WithdrawalCash (account, amount) =

    match amount with
    | v when account.Balance.CurrentAmount - v < 0 ->
       NotEnoughMoneyForWithdrawal(account, amount)

    // more when clauses can go here

    | _ ->
      let newBalance = account.Balance.CurrentAmount - amount 
      CashWithdrawnEvent(account, newBalance) 

For the general case of enumerating some sequence and stopping when a particular condition is met, consider "Seq.takeWhile", as in:

let MySeq = seq {
    while true do
        yield someValue
    }

let code () =
    MySeq
    |> Seq.takeWhile ( fun v -> ShouldIContinueWorkingTest(v) )
    |> Seq.iter ( fun v -> DoWork(v) )
like image 36
James Hugard Avatar answered Oct 24 '22 01:10

James Hugard