我正在查看以下 F# 行
for i = 0 to i=10 do
Console.WriteLine("Hello")
我想知道上面的行不是一个语句而不是一个表达式吗?
F# 中的所有内容不应该都是表达式吗?
如前所述,F# 中的每个语法结构都是一个表达式。F# 不区分语句和表达式(因此我想说 Robert 发布的 WikiPedia 引用有点误导 - F# 没有语句)。
实际上,上述情况并不完全正确,因为 F# 计算表达式中的某些构造,例如let!
not expressions,但我们可以忽略它。
这意味着什么?在 C# 中,for
方法调用的语法定义如下:
statement := foreach(var v in <expression>) <statement>
| { <statement> ... <statement> }
| <expression>;
| (...)
expression := <expression>.<ident>(<expression>, ..., <expression>)
| <literal>
| <expression> + <expression>
| (...)
这是非常简化的,但它应该给你的想法 - 语句是不评估值的东西。它可以是foreach
循环(其他循环)、语句块(具有多个语句)或带有分号的表达式(其中表达式的结果void
被忽略或被忽略)。例如,表达式是方法调用、原始文字(字符串、整数)或二元运算符。
这意味着您不能在 C# 中编写某些内容 - 例如,方法调用的参数不能是语句(因为语句不会评估为值!)
另一方面,在 F# 中,一切都是表达式。这意味着只有一个语法类别:
expression := for v in <expression> do <expression>
| <expression>; <expression>
| <expression>.<ident>(<expression>, ..., <expression>)
| <literal>
| <expression> + <expression>
| (...)
这意味着在 F# 中,所有语法结构都是表达式,包括for
循环和其他循环。of 的主体for
也是一个表达式,但如果表达式评估为某个值(即42
),则没有意义,因此类型要求主体的结果是unit
(不携带任何信息)。同样,排序 ( <expr>; <expr>
) 中的第一个表达式应该返回unit
- 排序的结果是第二个表达式的结果。
这使得语言更简单、更统一,但你可以写一些奇怪的东西:
let x = (for i in 0 .. 10 do printfn "%d" i); 42
这将打印从0
to的数字10
,然后将值定义x
为42
。赋值是表达式 ( <expr>; <expr>
) 的序列,其中第一个是for
循环(它有一个类型unit
,因为它不计算任何东西),第二个是42
,它的计算结果是 42。
F# 中的每个语句,包括 if 语句和循环,都是具有明确返回类型的可组合表达式。不返回任何值的函数和表达式的返回类型为 unit。
在像 F# 这样的语言中,语句只是返回 type 值()
的表达式unit
。由于该unit
类型只有一个值,它不传达任何信息,因此返回类型 unit 的值表示“如果我正在做任何事情,那么它是通过副作用的方式”,例如打印到控制台或写入磁盘。
Note that not everything is an expression in F#. Type definitions are not expressions. Patterns are not expressions. And so on...