В этом вопросе рассматривается Ловушка синтаксиса OCaml: несколько позволяет использовать разделители.

С точки зрения программирования OCaml, как можно иметь несколько операторов let, которые выполняются перед одним let ... in, не превращая все объявления в выражения?

Например,

let f x = x + 1
let g x = x + 2 
let h x = x + 3

Компилируется без проблем, но

let f x = x + 1 
let g x = x + 2 
let h x = x + 3 in (Printf.printf "%d \n" (f (h (g 3))) ; ())

Не работает, потому что первые два являются декларациями, тогда как последний является выражением. То же самое относится и к переменным. Один из способов исправить эту ошибку - это вставить первые два let в выражения и вложить let...in. Тем не менее, это кажется довольно утомительным и неловким:

let f x = x + 1 in
  let g x = x + 2 in
    let h x = x + 3 in (Printf.printf "%d \n" (f (h (g 3))) ; ())

В качестве альтернативы можно представить длинный файл исходного кода OCaml, начинающийся с нескольких let объявлений глобальных переменных и одного let...in выражения в середине. В этом случае кажется, что ;; необходимо завершить объявления сверху, чтобы let... in работал, но использование ;; рекомендовано в документации.

Есть ли другой способ написать это (более элегантно)?

0
BearAqua 28 Май 2019 в 19:14

2 ответа

Лучший ответ

1

let <patt> = <expr>

Который имеет следующую семантику - вычислить выражение <expr> и применить его к шаблону <patt>, если есть совпадение, а затем обогатить глобальный контекст переменными, связанными в шаблоне <patt>.

Поэтому обычное решение вашей проблемы будет

let f x = x + 1 
let g x = x + 2 
let h x = x + 3

let () = 
 Printf.printf "%d \n" (f (h (g 3))); 
 ()

По историческим причинам OCaml допускает выражения, такие как 1, "hello" или let x = 1 in x + x на верхнем уровне, при условии, что вы разделяете их, используя ;;. В основном это связано с совместимостью с интерактивной системой верхнего уровня, так что вы можете использовать OCaml в качестве калькулятора. Я бы посоветовал не использовать ;; в реальных программах OCaml, написанных для использования компилятором.


1) Вы называете их объявлениями , хотя на самом деле они являются определениями, однако для нашего случая это не имеет значения.

3
ivg 28 Май 2019 в 16:30

Не знаю, изящнее ли это, но

let f x = x + 1 
let g x = x + 2 
let _ = let h x = x + 3 in Printf.printf "%d \n" (f (h (g 3)))

Компилирует и запускает.

1
melpomene 28 Май 2019 в 16:28