2015-10-21 3 views
1

Я в настоящее время изучаю OCaml сегодня, я подошел к этому фрагменту кода.Разница ключевого слова функции и совпадение с в OCaml

let rec tree_to_list acc = function 
    | Leaf x -> x::acc 
    | Node (t1,t2) -> tree_to_list (tree_to_list acc t2) t1 

Насколько я понимаю, эта функция делает то же самое, чем это один

let rec tree_to_list2 acc t = match t with 
    | Leaf x -> x::acc 
    | Node (t1, t2) -> tree_to_list t1 (tree_to_list2 acc t2) 

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

function x -> x + 2 

Может кто-то пожалуйста, помогите мне понять синтаксис первой функции, и если какой-либо разница в плане того, как обе функции вычисляются. Заранее спасибо.

+0

Да, немного запутанный, у нас есть 3 синтаксиса определения функций и сопоставление шаблонов на стороне привязки параметра - да, вы можете сопоставить соответствие слева от знака равенства. –

+0

Колин Г.Д. Есть русский на английском языке. Введение в функциональное программирование в OCaml (www.france-universite-numerique-mooc.fr). Он все еще открыт. Он начал эту неделю (с введением Ксавьера Лероя). –

+0

Hi @ V.Michel Я знаю об этом mooc, мои учителя - это те, кто стоит за ним, но спасибо вам в любом случае. –

ответ

2

Функции в OCaml определяются заданием шаблонов для аргументов. Общий случай простого имени переменной (например, acc в вашей первой функции) - это всего лишь особый тип шаблона, который соответствует всем значениям.

Таким образом, один из способов взглянуть на это состоит в том, что fun определяет функцию с любым количеством аргументов, каждая из которых может быть задана одним шаблоном. С другой стороны, function определяет функцию с одним аргументом, которая может быть задана любым числом шаблонов.

# let dot = fun (a, b) (c, d) -> a *. c +. b *. d 
val dot : float * float -> float * float -> float = <fun> 

# let geti = function None -> 0 | Some i -> i;; 
val geti : int option -> int = <fun> 

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

То есть,

let f = fun p1 p2 -> ... 

можно записать в виде

let f p1 p2 = ... 

Так, например:

let dot (a, b) (c, d) = a *. c +. b *. d 

Ваша первая функция используется сочетание двух (краткой fun и function справа).

0

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

let f = (+) 2;; 

Это добавит 2 к любому числу и аргу явно не назван.

3

Насколько я понимаю, эта функция делает то же самое, чем это один

Вы правильны в том, что два фрагмента кода, оцениваются одинаково.

Может кто-то пожалуйста, помогите мне понять синтаксис первой функции

Как кажется @JeffreyScofield получить ответы эту часть очень хорошо, я остановлюсь на второй части.

если разница в терминах того, как обе функции вычисляются

ПЯ; др там нет никакой разницы, и сборка производится на самом деле идентичны. Мы будем использовать простой пример Фибоначчи, чтобы показать сборку, испущенную с использованием нот match with и function.

let rec fib n = match n with 
| 0 -> 0 
| 1 -> 1 
| i -> fib (i - 1) + fib (i - 2) 

и

let rec fib = function 
| 0 -> 0 
| 1 -> 1 
| i -> fib (i - 1) + fib (i - 2) 

оба производят

fib: 
    subq $24, %rsp 
.L102: 
    cmpq $1, %rax 
    je .L100 
    cmpq $3, %rax 
    je .L101 
    movq %rax, 0(%rsp) 
    addq $-4, %rax 
    call fib 
.L103: 
    movq %rax, 8(%rsp) 
    movq 0(%rsp), %rax 
    addq $-2, %rax 
    call fib 
.L104: 
    movq 8(%rsp), %rbx 
    addq %rbx, %rax 
    decq %rax 
    addq $24, %rsp 
    ret 
.L101: 
    movq $3, %rax 
    addq $24, %rsp 
    ret 
.L100: 
    movq $1, %rax 
    addq $24, %rsp 
    ret 

Примечание: Я намеренно удалены .align S и тому подобное.

Чтобы проверить утверждение, что они производят один и тот же узел (и, таким образом, оценивается то же самое), вы можете просто поместить каждую функцию в файле, а затем запустить

$ ocamlopt -S fib-with-match.ml 
$ ocamlopt -S fib-with-function.ml 

когда вы diff два, вы должны увидеть его вернуть без разницы:

$ diff fib-with-match.s fib-with-function.s 
$ 

это очень часто имеют функции, которые содержат только match выражения в OCaml, так как сказал @JeffreyScofield, function имеет аргумент, который может быть использован для картины ма собный. Таким образом, это синтаксический сахар.

Источник:

1

Мой способ объяснить определение функции в OCaml:

Это эквивалент:

let name p1 p2 ... pn = expr 
let name = function p1 -> function p2 -> ... -> function pn -> expr 
let name = fun p1 p2 ... pn -> expr 

Как памятка Риза его:

  • первый является синтаксическим сахаром,

  • вторым это то, что он действительно внутренне,

  • третьего наследство от КАМЛ.

Теперь function принимает только один аргумент, но он часто используется как это - это эквивалент, вы соответствия на р3:

let f1 p1 p2 p3 = match p3 with 
| [] -> expr 
| ... 

let f2 p1 p2 = function 
    | [] -> expr 
    | ... 

Вы видите второй вариант сохраняет некоторые символы исходного , удаляя визуальный беспорядок. Или больше: нет необходимости связывать значение с p3 без использования переменной p3, поскольку сопоставление шаблонов является наилучшей конструкцией связывания.

Смежные вопросы