I have a while-do loop nested inside a while-do loop in my program, due to it needing to iterate in two dimensions through an array of arrays, and originally my loop looked like this:
while ( tHeightIndex < tSearchHeight - 1 ) && tContinue do while ( tWidthIndex < tSearchWidth - 1 ) && tContinue do let tCurrentValue = tLargeArray.[tHeightIndex].[tWidthIndex] if tCurrentValue = tFirstSmallPixel then tMatch <- ArrayFunctions.SearchSubset tSmallArray tLargeArray ( tHeightIndex, tWidthIndex ) if tMatch then tContinue <- false if tMatch = false && tContinue = true then tWidthIndex <- tWidthIndex + 1 if tMatch = false && tContinue = true then tWidthIndex <- 0 // Reset to search next row tHeightIndex <- tHeightIndex + 1 tMatch, tWidthIndex, tHeightIndex
However, seeing as I'm doing this project entirely to learn better functional programming practices, I refactored that nested loop into two tail-recursive functions. This code passes my unit tests and appears to work correctly, so I would like advice about the style of the code and whether there's better ways I can make the code read clearly.
The relevant part to the original while-do loop is located after the declaration of
module ImageSearch = open ImageFunctions let SearchBitmap (smallBitmap:Bitmap) (largeBitmap:Bitmap) = let smallArray = Transform2D <| LoadBitmapIntoArray smallBitmap let largeArray = Transform2D <| LoadBitmapIntoArray largeBitmap let searchWidth = largeBitmap.Width - smallBitmap.Width let searchHeight = largeBitmap.Height - smallBitmap.Height let firstSmallPixel = smallArray.. let WidthLoop heightIndex = let rec WidthLoopRec heightIndex widthIndex = let ContinueLoop () = WidthLoopRec heightIndex (widthIndex + 1) let currentLargePixel = largeArray.[heightIndex].[widthIndex] match ( widthIndex < searchWidth , currentLargePixel = firstSmallPixel ) with | ( true , true ) -> let foundImage = ArrayFunctions.SearchSubset smallArray largeArray ( heightIndex, widthIndex ) if foundImage then widthIndex , foundImage else ContinueLoop () | ( true , false ) -> ContinueLoop () | ( false, _ ) -> widthIndex , false WidthLoopRec heightIndex 0 let HeightLoop () = let rec HeightLoopRec heightIndex = let widthIndex, foundImage = WidthLoop heightIndex match ( foundImage, heightIndex < searchHeight ) with | ( false , true ) -> HeightLoopRec ( heightIndex + 1 ) | ( _ , _ ) -> foundImage , widthIndex , heightIndex HeightLoopRec 0 HeightLoop ()