Проблемы с сопоставлением с образцом в F # - PullRequest
3 голосов
/ 21 февраля 2011

Мне нужна помощь с паттерном в F #. Я хочу сделать это:

            let y x =
            match x with
            | x.Contains("hi") -> "HELLO"
            | x.Contains("hello") -> "HI"
            | x -> x

Но это не работает. Что не так?

Ответы [ 3 ]

9 голосов
/ 21 февраля 2011

Самый простой подход - это использовать команду защиты в ваших матчах.

let y (x:string) =
  match x with
  | x when x.Contains("hi") -> "HELLO"
  | x when x.Contains("hello") -> "HI"
  | x -> x
7 голосов
/ 21 февраля 2011

Условия, которые включают вызовы методов, могут быть записаны только в when guard, как пишет pblasucci.

Если вы хотите использовать некоторые расширенные функции F # (например, если вам нужно много писать), вы можете определить активный шаблон для проверки подстроки (но не беспокойтесь об этом, если вы только изучаете F #) :

let (|Contains|_|) (what:string) (str:string) = 
  if str.Contains(what) then Some(str) else None

Затем вы можете написать что-то вроде (интересно, вы также можете использовать вложенные шаблоны для проверки на наличие нескольких слов, но то же самое можно написать с использованием шаблона &):

match "hello world" with
| Contains "hello" (Contains "world" str) -> 
    printfn "%s contains both hello and world!" str
| Contains "hello" str -> 
    printfn "%s contains only hello!" str
| _ -> ()
5 голосов
/ 21 февраля 2011

Я думаю, что мой ответ здесь на предыдущий вопрос может помочь вам немного лучше понять соответствие шаблону.

Однако, для того, что вы пытаетесь сделать, я бы, вероятно, придерживался простых выражений if / then / else:

let y x =
  if x.Contains("hi") then "HELLO"
  elif x.Contains("hello") then "HI"
  else x

Создание специального Contains активного шаблона, такого как @Tomas Petricek, также является вариантом, но я считаю, что если я действительно собираюсь выполнить какое-то серьезное сопоставление с строковым шаблоном, то я просто придерживаюсь пары верных регулярных выражений активных шаблонов. :

open System.Text.RegularExpressions

///Match the pattern using a cached interpreted Regex
let (|InterpretedMatch|_|) pattern input =
    if input = null then None
    else
        let m = Regex.Match(input, pattern)
        if m.Success then Some [for x in m.Groups -> x]
        else None

///Match the pattern using a cached compiled Regex
let (|CompiledMatch|_|) pattern input =
    if input = null then None
    else
        let m = Regex.Match(input, pattern, RegexOptions.Compiled)
        if m.Success then Some [for x in m.Groups -> x]
        else None

и для этой проблемы используйте их так:

let y = function // shorthand for let y x = match x with ...
    | CompiledMatch @"hi" _ -> "HELLO"
    | CompiledMatch @"hello" _ -> "HI"
    | x -> x

Мне это нравится, потому что он с легкостью охватывает Contains, StartsWith, EndsWith, Equals и далее:

let y = function
    | CompiledMatch @"^hi$" _ -> "Equals"
    | CompiledMatch @"^hi" _ -> "StartsWith"
    | CompiledMatch @"hi$" _ -> "EndsWith"
    | CompiledMatch @"leadinghiending" _ -> "Beyond"
    | CompiledMatch @"hi" _ -> "Contains"
    | x -> x

(обратите внимание, что буквенные строки, введенные @, на самом деле не нужны ни для одного из этих примеров регулярных выражений, но я всегда использую их, так как они вам нужны чаще, чем с регулярными выражениями).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...