F # явное совпадение с синтаксисом функций
Извините за неопределенное название, но часть этого вопроса - это то, что называются этими двумя стилями синтаксиса:
let foo1 x =
match x with
| 1 -> "one"
| _ -> "not one"
let foo2 = function
| 1 -> "one"
| _ -> "not one"
Другая часть - какая разница между этими двумя, и когда я хотел бы использовать один или другой?
Ответы
Ответ 1
Версия соответствия называется выражением соответствия шаблону. Версия функции называется "функцией сопоставления с образцом". Найдено в разделе 6.6.4 spec.
Использование одного над другим - вопрос стиля. Я предпочитаю использовать только функциональную версию, когда мне нужно определить функцию, которая является только выражением соответствия.
Ответ 2
Про второй синтаксис заключается в том, что при использовании в лямбда он может быть немного более кратким и читаемым.
List.map (fun x -> match x with | 1 -> "one" | _ -> "not one") [0;1;2;3;1]
против
List.map (function 1 -> "one" | _ -> "not one") [0;1;2;3;1]
Ответ 3
Версия функции - это короткая рука для синтаксиса полного соответствия в специальном случае, когда оператор соответствия - это целая функция, и функция имеет только один аргумент (количество кортежей считается одним). Если вы хотите иметь два аргумента, вам нужно использовать синтаксис полного соответствия *. Вы можете увидеть это в следующих двух функциях.
//val match_test : string -> string -> string
let match_test x y = match x, y with
| "A", _ -> "Hello A"
| _, "B" -> "Hello B"
| _ -> "Hello ??"
//val function_test : string * string -> string
let function_test = function
| "A", _ -> "Hello A"
| _, "B" -> "Hello B"
| _ -> "Hello ??"
Как вы видите, версия соответствия принимает два отдельных аргумента, тогда как версия функции принимает один аргумент с чередованием. Я использую версию функции для большинства функций одного аргумента, так как я обнаружил, что синтаксис функции выглядит более чистым.
* Если вы действительно хотите, чтобы версия функции имела правильную подпись типа, но на мой взгляд она выглядит довольно уродливо - см. пример ниже.
//val function_match_equivalent : string -> string -> string
let function_match_equivalent x y = (x, y) |> function
| "A", _ -> "Hello A"
| _, "B" -> "Hello B"
| _ -> "Hello ??"
Ответ 4
Они делают то же самое в вашем случае - ключевое слово function
действует как комбинация ключевого слова fun
(для создания анонимной лямбда), за которым следует ключевое слово match
.
Таким образом, технически эти два являются одинаковыми, с добавлением fun
:
let foo1 = fun x ->
match x with
| 1 -> "one"
| _ -> "not one"
let foo2 = function
| 1 -> "one"
| _ -> "not one"
Ответ 5
Просто ради полноты, я просто добрался до страницы 321 Expert FSharp:
"Примечание. Листинг 12-2 использует форму выражения function pattern-rules -> expression
. Это эквивалентно (fun x -> match x with pattern-rules -> expression)
и особенно удобно как способ определения функций, работающих непосредственно над дискриминационными объединениями."
Ответ 6
функция допускает только один аргумент, но позволяет сопоставлять шаблоны, а fun - более общий и гибкий способ определения функции. Посмотрите здесь: http://caml.inria.fr/pub/docs/manual-ocaml/expr.html
Ответ 7
Два синтаксиса эквивалентны. Большинство программистов выбирают один или другой, а затем последовательно используют его.
Первый синтаксис остается более читаемым, когда функция принимает несколько аргументов перед началом работы.
Ответ 8
Это старый вопрос, но я брошу свои $0,02.
В общем, мне нравится версия match
, так как я пришел из мира Python, где "явное лучше, чем неявное".
Конечно, если информация о типе параметра не нужна, версия function
не может быть использована.
OTOH Мне нравится аргумент, сделанный Stringer
, поэтому я начну использовать function
в простых lambdas.