2016-11-22 80 views
2

我對F#是全新的(今天開始使用它),並且對函數式編程(我對Lisp有一點經驗)相對較新。我想通過在滿足某個條件時返回一個值來退出函數,以便不執行循環的其餘部分。這裏是什麼,我想要做一個C#圖解:返回值打破功能

bool CheckRow (int n, int i) 
{ 
    for(int j = 0; j < 9; j++) 
     if (n == sudoku[i][j]) 
      return false; 

    return true; 
} 

我試圖實現在F#相同功能的這樣的(數獨是一種array2D):

let CheckRow (n : int) (i : int) : bool = 

    for j = 0 to 8 do 
     if (n = sudoku.[i, j]) then 
      false 

    true 

不過,我得到以下錯誤在if中爲false:「這個表達式預計有單位類型,但是這裏的類型是bool」。從F#函數中「返回」的正確方法是什麼?

+3

的可能的複製[F#返回函數布爾值(http://stackoverflow.com/questions/19195346/f-returns-boolean-value-in-function) –

+0

我會在這裏假設你並沒有以一種慣用的方式來做這件事,我想你可以使用seq類型來幫助你,並且以更有效的方式來做它 –

+1

如果你認爲你需要從F#函數中「提早退出」,那通常就是你在思考錯誤的線索。在這裏,您想查看該行是否有滿足特定條件的任何值。這就是Array.exists函數的作用。 (或者'List.exists',或者'Seq.exists' - 見Bartek Kobylecki的回答)。 – rmunn

回答

3

通常情況下,您不應該先破壞函數,而是在某些情況下結束遞歸,否則遞歸調用函數。這裏遞歸可能被隱藏,因爲你在列表或矩陣上操作。

List.forall是那些在列表上實現遞歸併在第一次返回結果的函數之一。你可以寫你的功能是這樣的:

let CheckRow (expectedValue : int) (rowIndex : int) = 
    [0..8] |> List.forall (fun colIndex -> 
     sudoku.[rowIndex, colIndex] <> expectedValue) 
+2

我只會選擇seq而不是列表,因爲seq不依賴於具有所有值的序列... –

2

高階函數是好的,當然,但在某些時候有人寫一個循環(如實施高階函數),並且最終將是你,所以很高興知道如何在F#中編寫循環。有一個從F#中for循環中沒有提前返回,但其他類型的循環確實允許這樣的:

// While loop, imperative style 
let checkRow n i = 
    let mutable clear = true 
    let mutable j = 0 
    while clear && j < 9 do 
     clear <- n <> sudoku.[i, j] 
     j <- j + 1 
    clear 

// Tail-recursive style - more idiomatic F# 
let checkRow n i = 
    let rec loop j = 
     if j = 9 then true 
     elif sudoku.[i, j] = n then false 
     else loop (j + 1) 
    loop 0