为什么 space 在此代码中有所不同,在 F# 中

Why does a space make a difference in this code, in F#

我有这种类型:

type ClockEvent (name: string, interval: TimeSpan, callback: unit -> unit) =
    ...
    member this.Start () =
       ...

我是这样使用它的:

ClockEvent("autowrite", TimeSpan.FromSeconds(0.5), fun _ ->
    match databaseWriterAsync connectionString |> Async.RunSynchronously with
    | Ok _    -> ()
    | Error e -> error $"couldn't write to the candles and kwap to the database: {e.Describe()}"
).Start()

按预期工作。

但是如果我在 'ClockEvent' 和 '(' 之间添加一个 space,我得到:

ClockEvent ("autowrite", TimeSpan.FromSeconds(0.5), fun _ ->
    match databaseWriterAsync connectionString |> Async.RunSynchronously with
    | Ok _    -> ()
    | Error e -> error $"couldn't write to the candles and kwap to the database: {e.Describe()}"
).Start()

然后,突然:

Writer.fs(54, 20): [FS0597] Successive arguments should be separated by spaces or tupled, and arguments involving function or method applications should be parenthesized

我知道问题与末尾的“.Start()”有关,但我不明白 space 如何导致编译器以不同方式解释代码。

要添加更多上下文,棘手的是函数应用程序和方法调用之间在 F# 中存在细微差别。

原则上带空格和不带空格都可以写:

foo(14)  // Function call, but odd syntax with parentheses
foo (14) // The same, but now without space
foo 14   // This is how you typically write it

与方法调用相同,但这里的约定不同:

"abc".IndexOf('b') // Normal way of writing it
"abc".IndexOf 'b'  // You are allowed to have a space
"abc".IndexOf 'b'  // Parentheses around the 'a' expression

空格的问题是 F# 通常要求您将内容括起来:

foo (bar 1 (qux 2 3))

如果您必须通过方法调用来执行此操作(在 F# 的旧版本中就是这种情况),那将非常乏味:

("foo".Substring(1)).Equals("oo") // This looks ugly
("foo".Substring 1).Equals "oo"   // But you can have spaces

所以,特殊的 high-precedence 应用规则说如果你没有空格(看起来像一个方法调用),你不需要写括号:

"foo".Substring(1).Equals("oo") // Works thanks to high-precedence rule