F # явное совпадение против синтаксиса функции

87

Извините за расплывчатое название, но часть этого вопроса заключается в том, как называются эти два стиля синтаксиса:

let foo1 x = 
    match x with
    | 1 -> "one"
    | _ -> "not one"

let foo2 = function 
    | 1 -> "one" 
    | _ -> "not one"

Другая часть заключается в том, какая разница между ними, и когда я хотел бы использовать тот или другой?

Бенджол
источник

Ответы:

56

Версия соответствия называется «выражением сопоставления с образцом». Версия функции называется «функцией сопоставления с образцом». Найдено в разделе 6.6.4 спец .

Использование одного над другим - вопрос стиля. Я предпочитаю использовать только версию функции, когда мне нужно определить функцию, которая является только оператором соответствия.

Gradbot
источник
Спасибо. Хотя в функциональном программировании с использованием F # говорится, что использование ключевого слова function указывает на то, что это функция сопоставления с образцом, этот ответ и OP проясняют момент остановки мозга.
octopusgrabbus
Ссылка не работает.
MattMS
83

Плюс второго синтаксиса в том, что при использовании в лямбде он может быть немного более кратким и читабельным.

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]
Стрингер
источник
23

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

//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 ??"
Джошуа
источник
12

В вашем случае они делают то же самое - functionключевое слово действует как комбинация funключевого слова (для получения анонимной лямбды), за которым следует matchключевое слово.

Так что технически это одно и то же, с добавлением fun:

let foo1 = fun x ->
    match x with
    | 1 -> "one"
    | _ -> "not one"

let foo2 = function
    | 1 -> "one"
    | _ -> "not one"
Тим Робинсон
источник
1
Разве не наоборот - то funесть технически определяется в терминах function | _ -> ...?
Павел Минаев
1
Чтобы быть конкретным, fun x y -> ...было бы fun x -> fun y -> ..., а потом fun x -> ...было бы function | x -> .... Вот почему вы можете выполнять сопоставление с образцом, funнапример fun (x::xs) -> ....
Павел Минаев
10

Для полноты картины я только что перешел на страницу 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

Камачи
источник
почему вы говорите только 1 аргумент, а не только последний аргумент? возможно иметь более 1 аргумента и использовать «функцию». это интерпретация функции высшего порядка?
симбионт
4

Два синтаксиса эквивалентны. Большинство программистов выбирают один или другой и затем последовательно его используют.

Первый синтаксис остается более читабельным, если функция принимает несколько аргументов перед началом работы.

Паскаль Куок
источник
2

Это старый вопрос, но я брошу свои 0,02 доллара.

В целом мне больше нравится эта matchверсия, поскольку я пришел из мира Python, где «явное лучше, чем неявное».

Конечно, если требуется информация о типе параметра, functionверсию использовать нельзя.

OTOH Мне нравится аргумент, который приводит, Stringerпоэтому я начну использовать functionв простых лямбдах.

Soldalma
источник