分隔多个`let`声明,然后在OCaml中使用单个`let in`表达式

时间:2019-05-28 16:14:44

标签: ocaml let

这个问题是关于OCaml syntax trap: multiple lets using separators的。

就编程命令式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 个答案:

答案 0 :(得分:3)

如果我们坚持语法,即顶级项目只能是定义

的定义 1 ,那么理解OCaml语法会容易得多。
let <patt> = <expr>

具有以下语义-计算表达式<expr>并将其应用于模式<patt>,如果存在匹配项,则使用模式{{1 }}。

因此,解决您问题的常规方法是

<patt>

由于历史原因,OCaml允许在顶层使用let f x = x + 1 let g x = x + 2 let h x = x + 3 let () = Printf.printf "%d \n" (f (h (g 3))); () 1"hello"之类的表达式,但前提是您使用let x = 1 in x + x将它们分开。这主要是由于与交互式顶级系统的兼容性,因此您可以将OCaml用作计算器。我建议不要在为编译器使用而编写的实际OCaml程序中使用;;


1)您称它们为声明,尽管它们实际上是定义,但是对于我们而言,这并不重要。

答案 1 :(得分:1)

我不知道它是否更优雅,但是

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

编译并运行。