Разделение нескольких объявлений `let` с последующим единственным выражением` let in` в OCaml - PullRequest
0 голосов
/ 28 мая 2019

В этом вопросе рассматривается Синтаксическая ловушка 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 работал, но использование ;; рекомендуется в документации.

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

Ответы [ 2 ]

3 голосов
/ 28 мая 2019

Было бы намного легче понять синтаксис OCaml, если мы будем придерживаться грамматики, в которой элемент верхнего уровня может быть только определением 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) Вы называете их объявлениями , хотя на самом деле они являются определениями, однако для нашего случая это не имеет значения.

1 голос
/ 28 мая 2019

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

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)))

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

...