OCaml中函数定义导致后续let绑定触发语法错误求助
OCaml中
in关键字触发语法错误的原因及解决办法 以下代码编译时会在in关键字处触发Error: Syntax error:
let get_json file = try Yojson.Basic.from_file file with | Sys_error message when message = (file ^ ": No such file or directory") -> Printf.printf "File named '%s' not found\n" file ; exit 0 let json = 10 in let y = 1 + json in Printf.printf "%d %d" json y
而调换代码顺序后可正常运行:
let json = 10 in let y = 1 + json in Printf.printf "%d %d" json y let get_json file = try Yojson.Basic.from_file file with | Sys_error message when message = (file ^ ": No such file or directory") -> Printf.printf "File named '%s' not found\n" file ; exit 0
编译脚本如下:
EXECUTABLE = ft_turing COMPILER = ocamlc COMPILER_OPT = ocamlopt SRCDIR = ./src SRCSFILES = main.ml SRCS = $(addprefix $(SRCDIR)/,$(SRCSFILES)) OBJECTS = $(SRCS:.ml=.cmo) OBJECTS_OPT = $(SRCS:.ml=.cmx) all: $(EXECUTABLE) $(EXECUTABLE): $(OBJECTS) ocamlfind $(COMPILER) -o $@ -linkpkg -package yojson $^ %.cmo: %.ml ocamlfind $(COMPILER) -c -package yojson $<
错误原因
OCaml对顶级代码的语法规则有明确区分:
- 顶级
let定义(如let get_json ... = ...)属于全局绑定,不需要in关键字,定义结束后编译器会期待下一个顶级定义或代码终止。 let ... in ...是表达式语句,只能出现在允许表达式的上下文里,不能直接跟在顶级let定义之后——编译器会误将其解析为前一个顶级绑定的延续,从而触发语法错误。
调换顺序后,开头的let ... in ...作为顶级表达式是合法的(OCaml允许顶级表达式作为程序入口逻辑),后续的顶级let定义也符合语法规则,因此可以正常编译。
解决办法
有两种可行的修复方式:
方式1:将表达式包装为顶级let绑定
把let ... in ...表达式包裹进let () = ...,将其转为合法的顶级绑定,这也是OCaml编译型代码的规范写法:
let get_json file = try Yojson.Basic.from_file file with | Sys_error message when message = (file ^ ": No such file or directory") -> Printf.printf "File named '%s' not found\n" file ; exit 0 let () = let json = 10 in let y = 1 + json in Printf.printf "%d %d" json y
方式2:用;;分隔顶级定义和表达式
在函数定义和表达式之间添加;;,明确告诉编译器这是两个独立的顶级结构(;;更多用于OCaml交互环境,编译型代码中不推荐):
let get_json file = try Yojson.Basic.from_file file with | Sys_error message when message = (file ^ ": No such file or directory") -> Printf.printf "File named '%s' not found\n" file ; exit 0 ;; let json = 10 in let y = 1 + json in Printf.printf "%d %d" json y
内容的提问来源于stack exchange,提问作者artainmo
相关产品推荐
相关产品推荐

