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 firstSmallPixel
.
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.[0].[0]
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 ()