Возможно ли с простыми преобразованиями сопоставления с шаблоном F # игнорировать несопоставленные значения без предупреждения? - PullRequest
3 голосов
/ 13 мая 2010

Итак, я ранее задавал этот вопрос:

Может ли кто-нибудь помочь мне сравнить использование F # с C # в этом конкретном примере (выражения IP-адреса)?

Я просматривал опубликованный код и мне было интересно, можно ли написать этот код без предупреждения:

let [|a;b;c;d|] = s.Split [|'.'|]
IP(parseOrParts a, parseOrParts b, parseOrParts c, parseOrParts d)

Можно ли что-то сделать для шаблона соответствия _, не игнорируя? Без добавления чего-то вроде активных шаблонов? я хочу сделать код как можно более простым ... могу ли я сделать это без радикального изменения этого кода?

ПРИМЕЧАНИЕ: предупреждение следующее

Предупреждение Неполные совпадения с образцом в этом выражении. Например, значение '[| _; _; _; _; _ |] 'может указывать на случай, не охваченный шаблоном (ами).

Ответы [ 3 ]

5 голосов
/ 13 мая 2010

Вы можете попробовать

#nowarn "25"

перед частичной функцией.

Но, конечно, вы отключаете предупреждение, и я думаю, что это отключает его для всего файла. Я помню, как видел способ отключить предупреждения только для части файла, но сейчас не могу его найти.

Существует также опция компилятора --nowarn:25, но это еще хуже, поскольку она применяется ко всему проекту.


Чтобы сделать это правильно, вам нужно заменить две строки на три:

match Array.map parseOrParts (s.Split [|'.'|]) with
| [|a;b;c;d|] -> IP(a,b,c,d)
| _ -> failwith "Oh no!"   // preferably, your exception of choice goes here.
4 голосов
/ 13 мая 2010

Обратите внимание, что предупреждение говорит о том, что если после вызова String.Split нет точно 4 элементов, вы получите MatchFailureException .

Как уже говорили другие, лучший способ избавиться от предупреждения -

match s.Split(...) with
| [| a; b; c; d |] -> blah(a,b,c,d)
| _ -> raise <| new Exception("Expected exactly 4 parts") // or whatever
3 голосов
/ 13 мая 2010

Я знаю, что вы написали "без добавления таких вещей, как активные шаблоны", но я опубликую решение, которое использует их в любом случае. Они идеально подходят для подобных задач и представляют собой довольно стандартную функцию F #, поэтому на самом деле нет причин, по которым вы бы хотели их избежать. Использование здесь активных шаблонов делает код определенно более читабельным.

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

Вы можете определить активный шаблон, который соответствует, если строка отформатирована как IP-адрес (состоящий из четырех подстрок, разделенных "."):

let (|IPString|_|) (s:string) =
  match s.Split('.') with
  | [|a;b;c;d|] -> Some(a, b, c, d) // Returns 'Some' denoting a success
  | _ -> None                       // The pattern failed (string was ill-formed)

match s with 
| IPString(a, b, c, d) ->  
    // Matches if the active pattern 'IPString' succeeds and gives
    // us the four parts of the IP address (as strings)
    (parseOrParts a, parseOrParts b, parseOrParts c, parseOrParts d)
| _ -> failwith "wrong format"

Это правильный способ, который позволяет вам обрабатывать случай, когда строка неверна. Конечно, вы можете определить версию, которая никогда не завершится с ошибкой (и возвращает, например, 0.0.0.0, если строка неверна):

// This active pattern always succeeds, so it doesn't include the "|_|" part 
// in the name. In both branches we return a tuple of four values.
let (|IPString|) (s:string) =
  match s.Split('.') with
  | [|a;b;c;d|] -> (a, b, c, d)
  | _ -> ("0", "0", "0", "0")

let (IPString(a, b, c, d)) = str
(parseOrParts a, parseOrParts b, parseOrParts c, parseOrParts d)

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

...