中断函数的返回值
Posted
技术标签:
【中文标题】中断函数的返回值【英文标题】:return value to break function 【发布时间】:2016-11-22 13:54:31 【问题描述】:我对 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# 函数中“返回”的正确方法是什么?
【问题讨论】:
F# returning boolean value in function的可能重复 我在这里假设您并没有以惯用的方式执行此操作,我认为您可以使用 seq 类型来帮助您并以更实用的方式执行此操作 如果您认为需要“提前退出” F# 函数,这通常表明您对问题的思考有误。在这里,您想查看行中是否有任何值满足特定条件。这就是Array.exists
函数的用途。 (或List.exists
,或Seq.exists
——见Bartek Kobylecki 的回答)。
Control Flow 整个系列是一个不错的快速概览。
如果您刚刚开始使用 F#,您应该了解的两个资源:F# for Fun and Profit 是网络上任何地方对 F# 的最佳介绍,Exercism 是 F# 练习的优秀集合,大致按照从易到难的顺序,帮助您轻松思考函数。
【参考方案1】:
高阶函数当然很好,但在某些时候必须有人编写循环(例如,为了实现高阶函数),最终会是你,所以很高兴知道如何编写循环在 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
【讨论】:
【参考方案2】:通常您不需要提前中断函数,而是在某些情况下结束递归,否则递归调用函数。此处的递归可能会被隐藏,因为您正在对列表或矩阵进行操作。
List.forall
是在列表上实现递归并在第一次返回结果的函数之一。你可以这样写你的函数:
let CheckRow (expectedValue : int) (rowIndex : int) =
[0..8] |> List.forall (fun colIndex ->
sudoku.[rowIndex, colIndex] <> expectedValue)
【讨论】:
我会选择 seq 而不是 list 只是因为 seq 不依赖于具有所有值的序列...以上是关于中断函数的返回值的主要内容,如果未能解决你的问题,请参考以下文章