F#条件表达式,如果...则..else返回单位或()

时间:2018-07-13 13:36:40

标签: f# null expression conditional-operator nothing

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分支?

4 个答案:

答案 0 :(得分:9)

考虑以下代码:

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分支。

答案 1 :(得分:2)

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

答案 2 :(得分:1)

  

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返回if等同于类似于C的if 语句,而不是表达式。

答案 3 :(得分:1)

问题已经回答,所以我将继续进行自己的肤浅观察

在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

其他答案表明,有一种特殊情况是省略elseif表达式将产生一个unit值,这是我们与F#中的语句最接近的值。  由于if表达式的类型是单位,因此“ true”分支的类型必须为unit

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