F# breaking from while loop in complex statements - f#

I have such a function:
let ScanColors() =
for i in 1..54 do
let mutable c = Unchecked.defaultof<string>
if (i = 9) then
c <- "U - WHITE"
else
if (i <> 0 && i%9 = 0) then
MoveSensor(SensorPos.THIRD)
else
MoveSensor(
match ((i - (i/9)*9)%2 <> 0) with
| true -> SensorPos.SECOND
| false -> SensorPos.FIRST)
while (true) do
c <- ScanColor()
if (c = "ERR") then
CalibrateSensorPosition()
else
break
ResetSensorPosition()
in this function, in the whilestatement, I cannot use break, because as you know, break is not used in F#. I was looking for alternatives for break, and I saw this link:
F# break from while loop
But to be honest, I couldn't be sure whether this solution suits with my problem.

Sadly F# does not support break. There are various fairly complicated ways to deal with this (like this recent one or my computation builder), but those have disadvantages and make your code fairly complex.
The general way to deal with this is to rewrite the code using recursion - this will typically compile to the same IL as what you would write in C# using break and continue.
So, the while block in your snippet could be written as a function that calls itself recursively until the result is not "ERR" and then returns the c:
let rec scanWhileErr () =
let c = ScanColor()
if c = "ERR" then
CalibrateSensorPosition()
scanWhileErr()
else c
And then call this function from the main block:
if (i <> 0 && i%9 = 0) then
MoveSensor(SensorPos.THIRD)
else
MoveSensor(if (i - (i/9)*9)%2 <> 0 then SensorPos.SECOND else SensorPos.FIRST)
c <- scanWhileErr ()
ResetSensorPosition()
Aside, I also changed your match on Booleans into an ordinary if - when you have just two cases and they are Booleans, there is really no point in using match over if.
Also, I kept your mutable variable c, but I suspect that you no longer need it thanks to recursion.

Break does not exist in F#, personally I would try to avoid breaks even in C# as there are many alternative/cleaner ways to break a loop.
A simple fix while keeping your imperative code style will be this:
c <- ScanColor()
while (c = "ERR") do
CalibrateSensorPosition()
c <- ScanColor()
ResetSensorPosition()
But in F# it can be further compacted to this one-liner:
while (c <- ScanColor(); c = "ERR") do CalibrateSensorPosition()

Actually, I think this approach is fine, and worked in my case:
let mutable flag = true
while (flag = true) do
c <- ScanColor()
if (c = "ERR") then
CalibrateSensorPosition()
else
flag <- false
ResetSensorPosition()

I think that an easy way is when it happen that you need to have a "break" in a loop then you just make sure that the loop terminate.
an example of this could be that if we have a while loop that look like this
while i < upperlimit do
if a
then break

Related

F# break from while loop

There is any way to do it like C/C#?
For example (C# style)
for (int i = 0; i < 100; i++)
{
if (i == 66)
break;
}
The short answer is no. You would generally use some higher-order function to express the same functionality. There is a number of functions that let you do this, corresponding to different patterns (so if you describe what exactly you need, someone might give you a better answer).
For example, tryFind function returns the first value from a sequence for which a given predicate returns true, which lets you write something like this:
seq { 0 .. 100 } |> Seq.tryFind (fun i ->
printfn "%d" i
i=66)
In practice, this is the best way to go if you are expressing some high-level logic and there is a corresponding function. If you really need to express something like break, you can use a recursive function:
let rec loop n =
if n < 66 then
printfn "%d" n
loop (n + 1)
loop 0
A more exotic option (that is not as efficient, but may be nice for DSLs) is that you can define a computation expression that lets you write break and continue. Here is an example, but as I said, this is not as efficient.
This is really ugly, but in my case it worked.
let mutable Break = false
while not Break do
//doStuff
if breakCondition then
Break <- true
done
This is useful for do-while loops, because it guarantees that the loop is executed at least once.
I hope there's a more elegant solution. I don't like the recursive one, because I'm afraid of stack overflows. :-(
You have to change it to a while loop.
let (i, ans) = (ref 0, ref -1)
while(!i < 100 and !ans < 0) do
if !i = 66 then
ans := !i
ans
(This breaks when i gets to 66--but yes the syntax is quite different, another variable is introduced, etc.)
seq {
for i = 0 to 99 do
if i = 66 then yield ()
}
|> Seq.tryItem 0
|> ignore
Try this:
exception BreakException
try
for i = 0 to 99 do
if i = 66 then
raise BreakException
with BreakException -> ()
I know that some folks don't like to use exceptions. But it has merits.
You don't have to think about complicated recursive function. Of
cause you can do that, but sometimes it is unnecessarily bothersome
and using exception is simpler.
This method allows you to break at halfway of the loop body. (Break "flag" method is simple too but it only allows to break at the end of the loop body.)
You can easily escape from nested loop.
For these kind of problems you could use a recursive function.
let rec IfEqualsNumber start finish num =
if start = finish then false
elif
start = num then true
else
let start2 = start + 1
IfEqualsNumber start2 finish num
Recently I tried to solve a similar situation:
A list of, say, 10 pieces of data. Each of them must be queried against a Restful server, then get a result for each.
let lst = [4;6;1;8]
The problem:
If there is a failed API call (e.g. network issue), there is no point making further calls as we need all the 10 results available. The entire process should stop ASAP when an API call fails.
The naive approach: use List.map()
lst |> List.map (fun x ->
try
use sqlComd = ...
sqlComd.Parameters.Add("#Id", SqlDbType.BigInt).Value <- x
sqlComd.ExecuteScala() |> Some
with
| :? System.Data.SqlClient.SqlException as ex -> None
)
But as said, it's not optimal. When a failed API occurs, the remaining items keep being processed. They do something that is ignored at the end anyway.
The hacky approach: use List.tryFindIndex()
Unlike map(), we must store the results somewhere in the lamda function. A reasonable choice is to use mutable list. So when tryFindIndex() returns None, we know that everything was ok and can start making use of the mutable list.
val myList: List<string>
let res = lst |> List.tryFindIndex (fun x ->
try
use sqlComd = ...
sqlComd.Parameters.Add("#Id", SqlDbType.BigInt).Value <- x
myList.Add(sqlComd.ExecuteScala())
false
with
|:? System.Data.SqlClient.SqlException as ex -> true
)
match res with
| Some _ -> printfn "Something went wrong"
| None -> printfn "Here is the 10 results..."
The idiomatic approach: use recursion
Not very idiomatic as it uses Exception to stop the operation.
exception MyException of string
let makeCall lstLocal =
match lstLocal with
| [] -> []
| head::tail ->
try
use sqlComd = ...
sqlComd.Parameters.Add("#Id", SqlDbType.BigInt).Value <- x
let temp = sqlComd.ExecuteScala()
temp :: makeCall (tail)
with
|:? System.Data.SqlClient.SqlException as ex -> raise MyException ex.Message
try
let res = makeCall lst
printfn "Here is the 10 results..."
with
| :? MyException -> printfn "Something went wrong"
The old-fashion imperative approach: while... do
This still involves mutable list.

Ocaml: calling recursive function again

So I have a recursive function that takes in 2 ints, and a out_channel and basically prints line(a,a+1). It should do this until value of a is equal to b. I.e if a = 1, b = 5
line(1,2)
line(2,3)
...line(4,5)
> let rec print_line (out:out_channel)(a:int)(b:int) : unit =
if (a < b) then output_string out ("line("^string_of_int(a)^","^string_of_int(a+1)^")\n")
> ;;
I want to make it recursive where it keeps printing the line(a,a+1) until a is no longer less than b. How exactly do I call it again?
Any help would be appreciated.
So: first check whether a >= b in which case you are done and can return (). Otherwise print one line (the way you did) followed by recursive call to your function, with incremented a. So altogether:
let rec print_line (out:out_channel)(a:int)(b:int) : unit =
if a >= b then
()
else (
output_string out ("line("^string_of_int(a)^","^string_of_int(a+1)^")\n");
print_line out (a + 1) b
)

F# using accumulator, still getting stack overflow exception

In the following function, I've attempted to set up tail recursion via the usage of an accumulator. However, I'm getting stack overflow exceptions which leads me to believe that the way I'm setting up my function is't enabling tail recursion correctly.
//F# attempting to make a tail recursive call via accumulator
let rec calc acc startNum =
match startNum with
| d when d = 1 -> List.rev (d::acc)
| e when e%2 = 0 -> calc (e::acc) (e/2)
| _ -> calc (startNum::acc) (startNum * 3 + 1)
It is my understanding that using the acc would allow the compiler to see that there is no need to keep all the stack frames around for every recursive call, since it can stuff the result of each pass in acc and return from each frame. There is obviously something I don't understand about how to use the accumulator value correctly so the compiler does tail calls.
Stephen Swensen was correct in noting as a comment to the question that if you debug, VS has to disable the tail calls (else it wouldn't have the stack frames to follow the call stack). I knew that VS did this but just plain forgot.
After getting bit by this one, I wonder if it possible for the runtime or compiler to throw a better exception since the compiler knows both that you are debugging and you wrote a recursive function, it seems to me that it might be possible for it to give you a hint such as
'Stack Overflow Exception: a recursive function does not
tail call by default when in debug mode'
It does appear that this is properly getting converted into a tail call when compiling with .NET Framework 4. Notice that in Reflector it translates your function into a while(true) as you'd expect the tail functionality in F# to do:
[CompilationArgumentCounts(new int[] { 1, 1 })]
public static FSharpList<int> calc(FSharpList<int> acc, int startNum)
{
while (true)
{
int num = startNum;
switch (num)
{
case 1:
{
int d = num;
return ListModule.Reverse<int>(FSharpList<int>.Cons(d, acc));
}
}
int e = num;
if ((e % 2) == 0)
{
int e = num;
startNum = e / 2;
acc = FSharpList<int>.Cons(e, acc);
}
else
{
startNum = (startNum * 3) + 1;
acc = FSharpList<int>.Cons(startNum, acc);
}
}
}
Your issue isn't stemming from the lack it being a tail call (if you are using F# 2.0 I don't know what the results will be). How exactly are you using this function? (Input parameters.) Once I get a better idea of what the function does I can update my answer to hopefully solve it.

F# mutable function arguments

Is there a way to have mutable function arguments in F#, that would allow something like
let mutable i = 9
let somefun n = n <- 12; ()
somefun i
(* *not* a real-world example *)
I do understand that this can be made to work by wrapping it into a record type
type SomeRec = { mutable i: int }
let ri = { i = 9 }
let someotherfun r = r.i <- 12; ()
and that this can be done in a similar fashion for class members. However, even after browsing through the whole F# Language Specification (yes, I did!), there seems to be no syntax to allow the first case, and the compiler appears to be quite unhappy about my trying this. I was hoping there would be some sort of type annotation, but mutable cannot be used in such.
I also know that I should not be doing this sort of thing in the first place, but the first case (int binding) and the second (record type) are semantically identical, and any such objection would hold for both cases equally.
So I think that I am missing something here.
You can use ref as arguments
let v = ref 0
let mutate r =
r := 100
mutate v
printfn "%d" !v
Or byref keyword
let mutable v = 0
let mutate (r : byref<_>) =
r <- 100
mutate &v
printfn "%d" v
Use byref keyword which is equivalent to C# ref.
See Passing by reference.

How to Translate Dictionary of Functions

I struggled to think of a good title here, but hopefully my description makes up for it.
As a hobby side-project, I'm attempting to port an interpreter for a toy language (you have to pay for the book, just linking to show where I am coming from) from Go to F#.
This has all gone fine until the point where I am needing to call other functions in a dictionary of functions.
Here's a very simplified example of what the Go code tries to do written in F#:
let processA a remainingCharacters =
1
let processB b remainingCharacters =
2
let processC c remainingCharacters =
// this doesn't work, obviously, as funcMap is declared below
let problem = funcMap.[remainingCharacters.Head]
3 + problem
// i assume there is a better way of doing this, I'm just not sure what it is
let funcMap = dict[('a', processA); ('b', processB); ('c', processC)]
let processCharacter currentCharacter remainingCharacters =
let processFunc = funcMap.[currentCharacter]
processFunc currentCharacter remainingCharacters
let input = ['a'; 'b'; 'a'; 'c']
let processInput() =
let rec processInputRec currentCharacter (remainingCharacters: char list) sum =
if remainingCharacters.IsEmpty then
sum
else
let currentValue = processCharacter currentCharacter remainingCharacters
processInputRec remainingCharacters.Head remainingCharacters.Tail (sum + currentValue)
processInputRec input.Head input.Tail 0
let result = processInput()
sprintf "%i" result |> ignore
So basically, it is trying to map given input values to different functions and in certain cases, needing to refer back to that mapping (or at least getting at another one of those mapped functions) inside those functions.
How would I go about doing that in F#?
The order of compilation in F# is a feature, not a bug. It helps to make sure that your code is not spaghetti, that all dependencies are nice and linear.
The "loopback" scenarios like this one are usually solved via parametrization.
So in this particular case, if you want the specific functions to call processCharacter recursively, just pass it in:
let processA a remainingCharacters _ = // an extra unused parameter here
1
let processB b remainingCharacters _ = // and here
2
let processC c remainingCharacters procChar = // here is where the extra parameter is used
let problem = procChar (List.head remainingCharacters) (List.tail remainingCharacters)
3 + problem
...
let rec processCharacter currentCharacter remainingCharacters =
let processFunc = funcMap.[currentCharacter]
processFunc currentCharacter remainingCharacters processCharacter
Note, however, that, although this will solve your immediate problem, this will (probably) not work all the way, because you're not keeping track of which characters got consumed from the input. So that, if processC decides to process one more character, the surrounding code won't know about it, and upon return from processC will process the same character again. I'm not sure if this was your intent (hard to tell from the code), and if it was, please disregard this warning.
The usual approach to parsing a stream of inputs like this is to have each processing function return a pair - the result of the processing plus the tail of remaining inputs, e.g.:
let processA chars =
1, (List.tail chars)
Then the surrounding "driver" function would thread the returned tail of the list to the next processing function. This way, each processing function can consume not necessarily one, but any number of inputs - from zero to all of them.
This approach has been implemented in libraries, too. Take a look at FParsec.
Another note: your code seems very un-F#-y. You're not using many F# features, making your code longer and more complicated than it needs to be. For example, instead of accessing .Tail and .Head, it is customary to pattern-match on the list:
let rec processInputRec current rest sum =
match rest with
| [] -> sum
| (next, rest') ->
let currentValue = processCharacter current rest
processInputRec next rest' (sum + currentValue)

Resources