如何强制在ocaml中启动下一个表达式

时间:2016-05-23 23:17:15

标签: expression ocaml

我想编写一个实现grep基本用法的函数:匹配文件中的模式。我想match_file_pattern返回匹配行的列表。但是这里的代码无法编译,错误是:

  

错误:此表达式具有类型字符串列表          但是预期表达式为单位

代码是:

let match_file pattern file_name =
  let matched_lines = ref [] in
  let ic = open_in file_name in

  try
    while true
    do
      let line = input_line ic in
      if (Str.string_match (Str.regexp pattern) line 0)
      then
         matched_lines := line::!matched_lines
    done;**(*!matched_lines*)**(*I need add this to compile successfully*)
  with End_of_file ->
    close_in ic;
    List.rev !matched_lines;;

我认为错误是由ocaml引起的,close_in ic; List.rev !matched_lines被分组为“with”关键字的子表达式,因此其类型应与“try”表达式匹配。我试图找到打破close_in ic;List.rev !matched_lines之间关系的方法,但失败了。

3 个答案:

答案 0 :(得分:2)

您可以使用begin/end或括号:

let match_file pattern file_name =
  let matched_lines = ref [] in
  let ic = open_in file_name in

  begin
  try
    while true
    do
      let line = input_line ic in
      if (Str.string_match (Str.regexp pattern) line 0)
      then
         matched_lines := line::!matched_lines
    done
  with End_of_file -> close_in ic
  end;
  List.rev !matched_lines

答案 1 :(得分:1)

循环的类型是unit,即使它永远不会完成。类型检查器不知道,因此您需要使try下的表达式与异常处理程序具有相同的类型。

在这种情况下,您可以使用任意列表,例如[],但这会对读者产生误导,并且不会推广到提供正确类型的表达式可能更复杂的情况。

这里惯用的解决方案是放置一个assert false,如果进行评估会引发异常。与无限while循环不同,typechecker知道assert false不返回,并且它与任何类型都兼容,因为永远不会产生值:

try
  while true do
    ...
  done;
  assert false
with ... -> ...

答案 2 :(得分:0)

你的代码很好:

done之后的一个分号,用于指令排序,然后!matched_lines作为try代码部分的返回值,然后是with ...

这里没有含糊之处。编译器没有考虑到始终引发End_of_file

其余的是编码风格的问题。我喜欢对这些技术上要求的表达式发表(* never reached *)评论 - 对于assert false提案以及IMO也是一个好主意。