ZetCode

F# 条件语句

最后修改日期:2025 年 5 月 17 日

在本文中,我们将探讨 F# 中的条件语句以及它们如何根据布尔表达式控制程序流。理解条件逻辑对于在 F# 程序中做出决策至关重要,可以确保高效的执行路径。

F# 条件语句允许程序动态地评估表达式并执行不同的代码分支。该语言提供了 ifelifelse 结构,与其他编程语言类似,但具有函数式增强。由于 F# 是基于表达式的,条件语句始终返回值,使其更具组合性并能与函数式编程范式无缝集成。

与通常会导致副作用的命令式语言不同,F# 强调不变性和表达式,从而确保代码执行的清晰性和可预测性。通过利用简洁的条件表达式,开发人员可以编写干净、可维护的代码,同时避免不必要的复杂性。

单个条件

最简单的条件语句检查单个布尔表达式。在 F# 中,if 表达式在使用需要值的上下文时必须具有 else 分支,但在仅用于副作用的操作时可以省略它。

single_condition.fsx
open System

let r = Random().Next(-5, 5)

if r > 0 then 
    printfn "positive value" 

if r < 0 then 
    printfn "negative value" 

if r = 0 then
    printfn "zero" 

此示例显示了三个独立的 if 表达式,它们检查随机数。每个 if 都是独立的,可能不执行、执行一个或多个打印语句。

λ dotnet fsi single_condition.fsx
negative value

多个条件

对于互斥的条件,F# 提供了 elifelse if)分支。这些分支允许链接条件,其中只有一个分支会执行。

multiple_conditions.fsx
open System

let r = Random().Next(-5, 5)

if r > 0 then 
    printfn "positive value" 
elif r < 0 then 
    printfn "negative value" 
elif r = 0 then 
    printfn "zero" 

此版本使用 elif 来确保只打印一条消息。条件按顺序检查,直到其中一个匹配,然后跳过其余的。

λ dotnet fsi multiple_conditions.fsx
positive value

else if 是 F# 中 elif 的等效项。

multiple_conditions.fsx
open System

let r = Random().Next(-5, 5)

if r > 0 then 
    printfn "positive value" 
else if r < 0 then 
    printfn "negative value" 
else if r = 0 then 
    printfn "zero" 

可以使用 else if 重写之前的示例。行为保持不变,但语法略有不同。elif 关键字在 F# 中更具惯用性。

else 关键字

当没有先前的条件匹配时,else 分支充当“捕获一切”的选项。它必须放在 if 表达式的最后,并且不带条件。

else_keyword.fsx
open System

let r = Random().Next(-5, 5)

if r > 0 then 
    printfn "positive value" 
elif r < 0 then 
    printfn "negative value" 
else 
    printfn "zero" 

这里我们用 else 替换了最后的 elif。这使得零值情况更清晰,因为它处理了之前条件未捕获的任何内容。

λ dotnet fsi else_keyword.fsx
zero

If 作为表达式

与许多语言不同,F# 的 if 是一个返回值的表达式。所有分支必须返回相同的类型,并且以此方式使用时要求有 else 分支。

if_expression.fsx
let describeNumber n =
    if n > 0 then "Positive"
    elif n < 0 then "Negative"
    else "Zero"

printfn "%d is %s" 5 (describeNumber 5)
printfn "%d is %s" -3 (describeNumber -3)
printfn "%d is %s" 0 (describeNumber 0)

let absValue x = if x >= 0 then x else -x
printfn "Absolute value of -4: %d" (absValue -4)

这些示例显示了返回值的 if 表达式。describeNumber 返回字符串,而 absValue 返回数字。两者都包括所有必需的分支。

λ dotnet fsi if_expression.fsx
5 is Positive
-3 is Negative
0 is Zero
Absolute value of -4: 4

嵌套条件语句

If 表达式可以嵌套在其他 if 表达式中,以创建更复杂的决策树。正确的缩进对于可读性至关重要。

nested_conditionals.fsx
let categorizeTemp temp =
    if temp > 30 then "Hot"
    elif temp > 20 then
        if temp > 25 then "Warm"
        else "Pleasant"
    elif temp > 10 then "Mild"
    else "Cold"

printfn "15°C is %s" (categorizeTemp 15)
printfn "22°C is %s" (categorizeTemp 22)
printfn "27°C is %s" (categorizeTemp 27)

此示例显示了用于温度分类的嵌套条件语句。中间范围在“温暖”和“宜人”之间具有子分类。

λ dotnet fsi nested_conditionals.fsx
15°C is Mild
22°C is Pleasant
27°C is Warm

布尔运算符

可以使用布尔运算符,如 &&(and)、||(or)和 not 来构建复杂条件。括号有助于澄清评估顺序。

boolean_operators.fsx
let checkRange x y =
    if x > 0 && y > 0 then "Both positive"
    elif x > 0 || y > 0 then "One positive"
    elif not (x > 0 || y > 0) then "Neither positive"
    else "Impossible case"

printfn "%s" (checkRange 3 4)
printfn "%s" (checkRange -2 5)
printfn "%s" (checkRange -1 -1)

这演示了使用布尔运算符组合条件。not 运算符反转其操作数的结果。

λ dotnet fsi boolean_operators.fsx
Both positive
One positive
Neither positive

模式匹配替代方案

对于复杂的条件逻辑,模式匹配通常比嵌套的 if/elif 表达式提供更简洁的代码,尤其是在有多个测试值时。

pattern_matching.fsx
let describeNumberMatch n =
    match n with
    | x when x > 0 -> "Positive"
    | x when x < 0 -> "Negative"
    | _ -> "Zero"

let checkCoordinates x y =
    match x, y with
    | 0, 0 -> "Origin"
    | _, 0 -> "On X axis"
    | 0, _ -> "On Y axis"
    | _ -> "Somewhere else"

printfn "%s" (describeNumberMatch 7)
printfn "%s" (checkCoordinates 0 5)

这些示例显示了模式匹配作为 if 表达式的替代方案。when 子句允许对匹配的值添加附加条件。

λ dotnet fsi pattern_matching.fsx
Positive
On Y axis

F# 条件语句提供了在代码中做出决策的灵活方式。if/elif/else 表达式的工作方式与其他语言类似,但更强调面向表达式的编程。对于复杂条件,请考虑使用模式匹配,这通常是更简洁的替代方案。

作者

我叫 Jan Bodnar,我是一位充满热情的程序员,拥有丰富的编程经验。我自 2007 年以来一直撰写编程文章。至今,我已撰写了 1,400 多篇文章和 8 本电子书。我在教授编程方面拥有超过十年的经验。