Что значит "let () =" в Ocaml? - PullRequest
       24

Что значит "let () =" в Ocaml?

10 голосов
/ 23 сентября 2011

Есть коды вроде

let () = print_string "something" in
fn

в некоторых кодах OCaml.

Что это значит? Есть ли специальное значение для "()"? или это то же значение, что и

print_string "something";
fn

Ответы [ 2 ]

13 голосов
/ 23 сентября 2011

В этом let выражении нет ничего особенного в (), это просто шаблон. Все let выражения выглядят как let pattern = expression in other-expression. Здесь шаблон всегда будет совпадать, потому что print_string возвращает unit, а () является единственным значением этого типа. Таким образом, это просто еще один способ объединения двух выражений в одно, когда первое действительно больше оператора (возвращает unit).

Итак, вы правы, конструкция имеет почти то же значение, что и оператор ;. Единственная реальная разница в приоритете. Если, например, вы пишете

if x < 3 then
    print_string "something";
    f x

вы обнаружите, что f x всегда вызывается . Приоритет ; слишком низок, чтобы передать второе выражение под контроль if. Вот почему многие люди (включая меня) привыкли использовать let () = expression. Если вы напишите выше, как

if x < 3 then
    let () = print_string "something"
    in f x

f x вызывается только тогда, когда x меньше 3, что обычно является тем, что я хочу. По сути, приоритет let намного выше, чем ;.

Конечно, есть и другие способы получить этот эффект, но хорошая вещь в использовании let заключается в том, что вам не нужно ничего добавлять позже в коде (например, закрывающая скобка или end) , Если вы добавляете print_string в качестве оператора отладки, это удобный способ сохранить изменения локальными для одного места.

3 голосов
/ 23 сентября 2011

Ответ Джеффри абсолютно правильный, но еще один момент:

если вы напишите

fx "something";
fn

И вы испортили тип результата fx "something", компилятор выдаст предупреждение, которое может потеряться во время компиляции. С другой стороны, если вы напишите:

let () = fx "something" in
fn

Компилятор проверит, что результат fx "something" может быть сопоставлен с (), т. Е. Что он действительно имеет тип unit. Таким образом, если вы запутались, возникает ошибка, которая обычно более безопасна.

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

let _ = fx "something" in
fn

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

...