Enr*_*rba 2 ocaml syntax-error
我很抱歉在这里问这样一个基本问题,但在尝试编译以下代码时遇到语法错误,
let sum_of_squares_of_two_largest x y z =
let a :: b :: _ = List.sort (fun x y -> -(compare x y)) [x; y; z] in
a * a + b * b;
let rec factorial n =
if n = 0 then 1 else n * factorial (n - 1);
let e_term n = 1.0 /. float_of_int (factorial n);
let rec e_approximation n =
if n = 0 then (e_term 0) else (e_term n) +. (e_approximation (n - 1));
let rec is_even x = if x = 0 then true else is_odd (x - 1);
and is_odd x = not (is_even x);
let rec f_rec n =
if n < 3 then n else f_rec(n - 1) + 2 * f_rec(n - 2) + 3 * f_rec(n - 3);
Run Code Online (Sandbox Code Playgroud)
无信息的编译器告诉我第 19 行(文件的最后一行)存在语法错误。
File "source.ml", line 19, characters 0-0:
Error: Syntax error
Run Code Online (Sandbox Code Playgroud)
也就是说,第 19 行是一个空行,只有一个换行符。
;;我可以通过在每个函数定义的末尾添加而不是;.
我在某处缺少分号吗?
正如评论中所指出的,;它不是像许多其他(受 Algol 启发的)语言那样的语句终止符,而是一个序列运算符。它接受两个值,丢弃第一个值(但如果不是单位则发出警告)并返回第二个值。a; b因此大致相当于let _ = a in b.
您说您预计错误会显示类似的内容';' is missing the second operand.,但事实是:事实并非如此。直到它到达文件末尾(此时错误消息当然可以更智能,但可能不是很准确)。
;代码中每个后面的内容看起来像是一个完全有效的表达式,可能会产生一个值。例如,如果let rec factorial n = ...;had was ,则let rec factorial n = ... in 2表达式的值将是2。从编译器的角度来看,这里的问题是在表达式完成之前它就用完了文件。
正如您还发现的那样,;;实际上是一个语句终止符。或者也许顶级定义终止符是一个更好的术语(我不知道它是否有正式名称)。它在 REPL 中用于终止输入,但在正常的 OCaml 代码中不需要它,除非您混合顶级定义和表达式,而您永远不应该这样做。
;;然而,对于初学者来说,作为“隔板”仍然有用。如果您只用一个代替文件中间;;的 a ,您会发现编译器现在将错误位置指向那里。;这是因为;;在前面的表达式不完整的情况下终止定义。所以你现在知道之前有一个错误。(实际上在前面的表达式中,但由于整个文件是一个表达式,“在那之前”确实是我们能做的最好的事情)。