Отрицание строкового метода в лямбда-функции дает ошибку - PullRequest
0 голосов
/ 17 января 2020

Я вызываю строковый метод «содержит» в лямбда-функции и хотел бы отрицать его. Я думал, что это можно сделать с помощью 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

Пожалуйста, укажите на любые другие очевидные ошибки, которые я делаю .

Ответы [ 2 ]

4 голосов
/ 17 января 2020

Вам просто нужно добавить скобки вокруг аргумента функции not:

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

Без скобок компилятор интерпретирует ваш код как вызов not с двумя аргументами:

not (line.Contains) ("abbr.")
3 голосов
/ 17 января 2020
Синтаксис

F # не похож на C# (или C, или C ++, или Java)

В частности, F # не использует скобки для передачи аргументов функции. Вместо этого F # использует пробел для этого:

let x = f y z

Вы, конечно, можете заключать любые выражения в скобки, если хотите указать порядок операций, или просто по причинам c: 1008 *

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.")

Нет особого значения для паренов. С таким же успехом вы могли бы написать это:

line.Contains "abbr."

Это было бы эквивалентно.

Видите, что происходит? Еще нет? Ну, ладно, давайте попробуем добавить not к миксу:

not line.Contains "abbr."

Это теперь понятнее? Похоже, вы пытаетесь вызвать функцию not, и вы даете ей два аргумента: первый аргумент line.Contains, а второй аргумент "abbr."

Это не то, что вы имелось ввиду, верно? Вы имели в виду, вероятно, сначала вызвать line.Contains, передав его "abbr " в качестве аргумента, а затем передать результат этого в not

. Самый простой способ сделать это - использовать круглые скобки, чтобы указать порядок операций:

not (line.Contains "abbr.")

Или, альтернативно, вы можете использовать оператор <|, который предназначен специально для такого рода вещей. Он просто передает параметр в функцию, поэтому практически ничего не делает. Но дело в том, что это оператор, поэтому его приоритет ниже, чем вызов функции:

not <| line.Cobtains "abbr."
...