否定 lambda 函数中的字符串方法会出错

Negate a string method in a lambda function gives error

我正在 lambda 函数中调用字符串方法 "contains",并想否定它。我认为这可以用 not myString.Contains("abbr") 来完成,但它给了我错误

Successive arguments should be separated by spaces or tupled, and arguments involving function or method applications should be parenthesized

我的实际功能是这样的

open System.IO

let createWordArray filePath =
    File.ReadLines(filePath)
    |> Seq.filter (fun line -> line <> "")
    |> Seq.filter (fun line -> not line.Contains("abbr.")) // Error occurs here
    |> Seq.map (fun line -> line.Split(' ').[0])
    |> Seq.filter (fun word -> word.StartsWith("-") || word.EndsWith("-"))
    |> Seq.toArray

请指出我犯的任何其他明显错误。

您只需要在 not 函数的参数周围添加括号:

|> Seq.filter (fun line -> 
     not (line.Contains("abbr.")))

如果没有括号,编译器会将您的代码解释为对带有两个参数的 not 的调用:

not (line.Contains) ("abbr.")

F# 语法不像 C#(或 C、C++ 或 Java)

特别是,F# 使用括号来传递函数参数。相反,F# 为此使用空格:

let x = f y z

当然,如果您想指示操作顺序,或者只是出于美观原因,您可以自由地将任何术语括在括号中:

let x = f (y+5) z // parens for order of operations
let x = f (y) (z) // parens just for the heck of it

所以你看,当你写的时候:

line.Contains("abbr.")

parens没有特殊意义。你也可以这样写:

line.Contains "abbr."

这将是等效的。

看看发生了什么?还没有?好吧,好吧,让我们尝试将 not 添加到组合中:

not line.Contains "abbr."

现在清楚了吗?看起来您正在尝试调用 not 函数,并且给它两个参数:第一个参数是 line.Contains,第二个参数是 "abbr."

你不是这个意思吧?你的意思可能是先调用 line.Contains 将其作为参数传递给 "abbr ",然后将其结果传递给 not

最直接的方法是用括号表示运算顺序:

not (line.Contains "abbr.")

或者,您也可以使用运算符 <|,它专门用于此类操作。它只是将一个参数传递给一个函数,所以几乎什么都不做。但它的重点是它是一个运算符,所以它的优先级低于函数调用:

not <| line.Cobtains "abbr."