Явний збіг F # проти синтаксису функції


87

Вибачте за туманний заголовок, але частиною цього питання є те, як називаються ці два стилі синтаксису:

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

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

Інша частина - яка різниця між ними, і коли я хотів би скористатися тим чи іншим?

Відповіді:


56

Версія відповідності називається "виразом, що відповідає шаблону". Версія функції називається "функцією збігу зразків". Знайдено в розділі 6.6.4 специфікації .

Використання одного над іншим - це питання стилю. Я вважаю за краще використовувати версію функції лише тоді, коли мені потрібно визначити функцію, яка є лише оператором збігу.


Дякую. Хоча функціональне програмування за допомогою 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 експерта FSharp :

"Зверніть увагу, що в лістингу 12-2 використовується форма виразу function pattern-rules -> expression. Це еквівалентно (fun x -> match x with pattern-rules -> expression)та особливо зручно як спосіб визначення функцій, що працюють безпосередньо над дискримінованими спілками."


6

Функція допускає лише один аргумент, але дозволяє узгоджувати зразки, тоді як веселощі є більш загальним та гнучким способом визначення функції. Погляньте тут: http://caml.inria.fr/pub/docs/manual-ocaml/expr.html


чому ви говорите лише 1 аргумент замість лише останнього аргументу? можливо мати більше 1 аргументу та використовувати "функцію". це інтерпретація функції вищого порядку?
симбіонт

4

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

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


2

Це старе питання, але я кину свої $ 0,02.

Загалом, мені більше подобається matchверсія, оскільки я походжу зі світу Python, де "явне краще, ніж неявне".

Звичайно, якщо потрібна інформація про тип параметра, functionверсія не може бути використана.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.