2014-07-16 65 views
10

我注意到下面的代码编译和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应该是可选的,但在此处添加它会导致编译错误(“未预期的令牌”或“不完整的表达式”)。

  • 声明在模块或类中。这里也不是这种情况,do位于函数内部,不在模块或类中。

我也注意到,与#light "off",代码不编译(“意外的关键字结合‘做’”),但我没有发现任何会在轻量级语法部分要么解释。

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

+2

它被称为'do'绑定。我在规范中找不到它,但它[在MSDN上记录](http://msdn.microsoft.com/en-us/library/dd393786.aspx)。 – Daniel

+0

@Daniel这是我提到的第三种情况,在模块内部做“ “当你想要独立于函数执行代码*时使用do绑定*” – svick

+1

完成引用:_独立于函数*或值定义* ._第二种情况可能适用于函数。 – Daniel

回答

7

documentation on MSDN

do结合使用而不定义函数或值来执行代码。

即使该规范没有包含允许的地方的完整列表,但它仅仅是一个表达式,声明为unit类型。一些示例:

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

它通常被省略。前面的每个例子都是有效的,没有do。因此,do仅服务于断言表达式为unit

+0

我认为该规范不允许使用它,因为它没有被列为'expr'(§6和§A.2.3)的选项之一。 – svick

+0

在过去的几年里,我见过很多用于函数或方法的'do'的例子。如果这种行为不是有意的,那么这一点事实上是有效的。但是,我认为情况并非如此,在这一点上规范并不完整。 – Daniel

0

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

我实际上并不在spec这里function-defn可以有不止一个表达式看到,只要所有,但最后一个评估,以unit - 或者说所有,但在确定职能的最后一个表达式被忽略返回值。

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

+0

“我实际上没有在规范中看到'function-defn'可以有多个表达式”这是多亏'expr = expr; expr'规则以及轻量级语法使分号可选的事实。 – svick