为什么函数内部允许“do”?

时间:2014-07-16 11:43:41

标签: f# language-specifications

我注意到以下代码在VS 2013中编译并运行:

let f() =
    do Console.WriteLine(41)
    42

但是在查看F#3.0规范时,我无法通过这种方式找到do的任何提及。据我所知,do可以有以下用途:

  • 作为循环的一部分(例如while expr do expr done),情况并非如此。
  • 内部计算表达式,例如:

    seq {
        for i in 1..2 do
        do Console.WriteLine(i)
        yield i * 2
    }
    

    这里的情况并非如此,f不包含任何计算表达式。

    虽然让我感到困惑的是,根据规范,do后面应该跟in。由于轻量级语法,in应该是可选的,但在此处添加它会导致编译错误(“意外令牌' in'或表达不完整”)。

  • 模块或类中的语句。这也不是这种情况,do位于函数内部,不在模块或类中。

我还注意到,使用#light "off",代码无法编译(“意外的关键字'在绑定中执行”),但我没有找到任何可能的内容在轻量级语法一节中解释这一点。

基于这一切,我假设在函数内使用do这种方式不应该编译,但确实如此。我是否错过了规范中的内容?或者这实际上是编译器或规范中的错误?

2 个答案:

答案 0 :(得分:7)

来自documentation on MSDN

  

do绑定用于执行代码而不定义函数或值。

即使规范不包含允许的地点的综合列表,它也只是一个声明为unit类型的表达式。一些例子:

if ((do ()); true) then ()
let x: unit = do ()

一般省略。前面的每个示例都在没有do的情况下有效。因此,do仅用于断言表达式为unit类型。

答案 1 :(得分:0)

通过F# 3.0 specification表达式语法do expr选择class-function-or-value-defn(类型)[第8章,第2.5节]和module-function-or-value-defn(模块)[Ch 10,A.2.1.1]。

我实际上并没有在规范中看到function-defn可以有多个表达式,只要最后一个表达式计算为unit - 或者除了最后一个表达式之外的所有表达式都被忽略在确定函数返回值时。

所以,这似乎是文档中的疏忽。