【发布时间】:2011-02-11 20:29:30
【问题描述】:
如何在 F# 中编写无操作语句?
具体来说,如何改进以下匹配语句的第二个子句:
match list with
| [] -> printfn "Empty!"
| _ -> ignore 0
【问题讨论】:
如何在 F# 中编写无操作语句?
具体来说,如何改进以下匹配语句的第二个子句:
match list with
| [] -> printfn "Empty!"
| _ -> ignore 0
【问题讨论】:
为空的副作用使用单位:
match list with
| [] -> printfn "Empty!"
| _ -> ()
【讨论】:
unit类型的表达式。
Stringer 的答案当然是正确的。我认为澄清这是如何工作的可能很有用,因为“()”并不是真正的空语句或空的副作用......
在 F# 中,每段有效的代码都是一个表达式。像let 和match 这样的结构由一些关键字、模式和几个子表达式组成。 let 和 match 的 F# 语法如下所示:
<expr> ::= let <pattern> = <expr>
<expr>
::= match <expr> with
| <pat> -> <expr>
这意味着let 的主体或match 的子句主体必须是某个表达式。它可以是某个函数调用,例如ignore 0,也可以是某个值——在您的情况下,它必须是unit 类型的某个表达式,因为printfn ".." 也是unit 类型。
unit 类型是只有一个值的类型,写成()(也表示没有元素的空元组)。这确实有点类似于 C# 中的 void,只是 void 没有 任何 值。
顺便说一句:下面的代码可能看起来像一个语句序列,但它也是一个表达式:
printf "Hello "
printf "world"
F# 编译器在两行之间隐式添加;,; 是一个排序运算符,其结构如下:<expr>; <expr>。它要求第一个表达式返回unit,并返回第二个表达式的结果。
当您来自 C# 背景时,这有点令人惊讶,但它使语言出奇地优雅和简洁。它不会以任何方式限制您 - 例如,您可以编写:
if (a < 10 && (printfn "demo"; true)) then // ...
(这个例子并不是很有用——只是一个灵活性的演示)
【讨论】: