中断函数的返回值

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 不依赖于具有所有值的序列...

以上是关于中断函数的返回值的主要内容,如果未能解决你的问题,请参考以下文章

recv函数返回啥值?

一个方法可以有多少个参数多少个返回值 Java

一个方法可以有多少个参数多少个返回值 Java

周立功can通信中断原因

深返回时右值引用中断

如果 JSON 中存在值,则中断,但如果值为 null,则返回(kotlin)