2016-11-22 78 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