F# 条件表达式 if...then..else 返回单元或 ()

F# Conditional Expressions if...then..else returning unit or ()

F# 的条件表达式需要一个条件来检查,一个分支为真,一个分支为假。例如:

let x = 
    if ("hello" = null) 
    then true
    else false //error if else branch missing

但是,当涉及到 unit,又名 () 时,事情会变得很奇怪。

let y = 
    if ("hello" = null) 
    then raise <| new ArgumentNullException()
    else () //happy with or without else branch

更简单地说:

let z = 
    if ("hello" = null) 
    then ()
    else () //happy with or without else branch

为什么返回 unit 时不需要 else 分支?

The types of the values produced in each branch must match. If there is no explicit else branch, its type is unit. Therefore, if the type of the then branch is any type other than unit, there must be an else branch with the same return type.

如果您从第一个片段中删除 else,则等同于

let x = 
    if ("hello" = null) 
    then true
    else ()

不进行类型检查。

为什么?我猜是为了与 OCaml 兼容。

The else expr3 part can be omitted, in which case it defaults to else (). (7.7.2)

你可以认为 unit-returning if 相当于 C-like if statement 而不是表达式.

考虑以下代码:

let f a = if a > 5 then true

如果你调用 f 10,它 return 就是 true

现在,问问自己:f 2 return 应该做什么?我知道你会说 false,但是编译器是怎么知道的呢?我的意思是,在这两种情况下,您的意思很可能是 return true,不是吗?甚至,也许,在 a <= 5 情况下崩溃,谁知道呢?

因此,为了使程序成为 "complete"(即包含在每种情况下做什么的说明),您始终必须指定一个 else 分支。


然而,

unit特殊的

返回unit表示没有有意义的return值。 unit 本质上代表副作用:它意味着 returned 的东西是为了在外部世界产生一些影响。由于 F# 不是一种纯语言,因此 unit-return 这样的事情非常普遍。例如,调试日志记录:

let f x =
    if x < 42 then printfn "Something fishy, x = %d" x
    x + 5

有了这样的陈述,就没有歧义了:众所周知,else 分支也意味着 return ()。毕竟 unit 没有其他值了,不是吗?同时,总是在末尾添加 else () 会非常令人厌烦和混淆。因此,为了可用性,编译器在这种特定情况下不需要 else 分支。

问题已经回答了,所以我只是根据自己的肤浅观察跟进

在 F# 中,我们没有语句和表达式。在 F# 中,我们仅使用表达式来组合计算。这是一件好事

在 C# 中,if 是一个有意义的语句

if(x)
{
  return 1;
}

如果 x 为真,执行将停止,我们 return 向调用者返回结果:1.

在 F# 中,if 是一个表达式,这意味着 if 应该产生一个值,而不管已经采取了哪个分支。因此这没什么意义

if x then 1 // What value should else branch evaluate to?

我们必须指定两个分支

if x then 1 else 0

正如其他答案所指出的那样,省略 else 是一种特殊情况。 if 表达式将产生一个 unit 值,这是我们在 F# 中获得的最接近语句的值。 因为 if 表达式的类型是 unit,所以 "true" 分支的类型必须是 unit.

if x then ()         // This works
if x then () else () // This works
if x then 1          // This won't work, type mismatch

在 F# 中,if 是表达式而不是语句。每个表达式都需要 return 一个值。 ifelse 都需要 return 相同类型的值,因为 F# 是强类型语言。因此,如果没有 else 分支,则默认情况下它的类型为 unit,但如果您的 if return 的值的类型不是 unit,则您需要具有相同类型的 else