类型成员中的属性和let语句

时间:2013-05-10 14:21:14

标签: f#

我正在使用FsUnit在F#中编写一些单元测试,我注意到属性周围有一些奇怪的行为,并且在类型成员中使用语句,并且想知道是否有人可以解释它?

如果我写这样的测试:

[<Fact>] member test.
  ``Test that something works correctly`` () =

    let x = 1

    x + 2 |> should equal 3

我会在“x + 2”行的第一个字符上看到Visual Studio 2012中的错误:

  

表达式中出现意外关键字'let'或'use'。预期'in'或其他标记。

使用'let ... in'可以解决此错误,但如果您想使用多个错误,请让它快速混乱:

[<Fact>] member test.
  ``Test that something works correctly`` () =
    let x = 1
    in x + 2 |> should equal 3

我最终发现将属性放在一个单独的行上也会解决错误:

[<Fact>]
member test.
  ``Test that something works correctly`` () =

    let x = 1

    x + 2 |> should equal 3

任何人都可以提供有关第一个代码段导致错误但其他两个不会导致错误的原因的任何见解吗?

2 个答案:

答案 0 :(得分:5)

在第一个代码段中,您实际上有两个缩进错误。第一个问题是''Test that something works correctly''应该在member关键字后缩进。第二个是函数的主体应该在所有成员定义行之后缩进。

如果您修复了第一个错误:

[<Fact>] member test.
           ``Test that something works correctly`` () =
    let x = 1
    x + 2 |> should equal 3

编译器会发出“可能不正确的缩进”警告,您可以通过进一步缩进函数体来修复:

[<Fact>] member test.
           ``Test that something works correctly`` () =
             let x = 1
             x + 2 |> should equal 3

在第二个代码段中,使用in关键字触发verbose syntax,其中缩进无关紧要。在最后一个示例中,member恰好具有最低的缩进;你偶然有正确的缩进。

那就是说,你应该避免将成员定义分成多行。在大多数情况下,您可以使用let绑定而不是更详细的member绑定。

[<Fact>]
let ``Test that something works correctly``() =
    let x = 1
    x + 2 |> should equal 3

答案 1 :(得分:3)

如评论中所述,您可以在let之后或member之后添加该属性。这样,您可以将注释和成员定义放在一行:

let [<Fact>] ``Test that something works correctly``() =
   let x = 1
   x + 2 |> should equal 3

还有一种情况是您实际上需要来使用此语法。如果你有多个相互递归的函数(可以相互调用),那么你需要使用let rec ... and来定义它们,在这种情况下,你必须在and之后放置属性:

let rec [<Test>] a () = 10
and [<Test>] b () = 10

但以下不是有效的语法:

[<Test>] 
let rec a () = 10
[<Test>] 
and b () = 10