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

问题描述 投票:0回答:4

F# 的条件表达式需要一个条件来检查、一个 true 分支和一个 false 分支。例如:

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

为什么返回

else
时不需要
unit
分支?

f# null expression conditional-operator
4个回答
12
投票

考虑以下代码:

let f a = if a > 5 then true

如果您调用

f 10
,它会返回
true

现在,问自己:

f 2
应该返回什么?我知道你会说
false
,但是编译器怎么知道这一点呢?我的意思是,在这两种情况下,您都可能想让它返回
true
,不是吗?或者甚至可能在
a <= 5
的情况下崩溃,谁知道呢?

因此,为了使程序“完整”(即包含在每种情况下执行操作的说明),您始终必须指定一个

else
分支。


然而,

unit
特别

返回

unit
表示没有任何有意义的返回值。本质上,
unit
代表副作用:这意味着返回它的东西意味着对外部世界产生一些影响。由于 F# 不是一种纯粹的语言,因此这种
unit
返回的东西相当普遍。例如,调试日志记录:

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

有了这样的陈述,就没有歧义了:众所周知,

else
分支也意味着返回
()
。毕竟,
unit
没有其他值,不是吗?同时,总是在末尾添加
else ()
会非常烦人且令人困惑。因此,为了可用性,编译器在这种特定情况下不需要
else
分支。


5
投票

在 F# 中,

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


2
投票

每个分支中生成的值的类型必须匹配。如果没有显式的 else 分支,则其类型为 unit。因此,如果then分支的类型是unit以外的任何类型,则必须有一个具有相同返回类型的else分支。

如果从第一个片段中删除

else
,则相当于

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

不进行类型检查。

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

else expr3
部分可以省略,在这种情况下它默认为
else ()
。 (7.7.2)

您可以将

unit
-返回
if
视为与 C 语言
if
语句 等价,而不是表达式。


2
投票

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

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

在 C# 中,

if
是一个有意义的语句

if(x)
{
  return 1;
}

如果

x
为 true,则停止执行,并将结果返回给调用者:
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
© www.soinside.com 2019 - 2024. All rights reserved.