Ocaml:将模式匹配表达式转换为 if 表达式(if...then...else)

Ocaml : transform a pattern matching expression into if expression (if... then... else)

我正在尝试编写这个模式匹配递归表达式

let rec drop_last l =
match l with
| [] -> []
| [_] -> [] 
| h::t -> h :: drop_last t ;;

作为 'if statement' 递归表达式。 我已经开始执行以下操作:

let rec drop_last2 l =
if l = [] then [] else 
if l = [_] then [] else
l = List.hd::List.tl then List.hd::drop_last2 (List.tl l);;

但是,我从编译器中收到语法错误。有人能告诉我应该如何修改此 if 语句 使其正确吗?

构造 [_] 是一个模式,而不是一个值。因此,您不能使用 = 将其与您尝试做的值进行比较。

我认为,要做的事情就是集中精力考虑列表的长度。模式 [] 在长度为 0 时匹配,模式 [_] 在长度为 1 时匹配。您可以在 if 语句中使用这些事实。

正如 Jeffrey 所说,[_] 是一种模式而不是一个值,您无法与之比较。

并且在 l = List.hd::List.tl 首先它是不正确的,List.hd 是一个接受列表的函数并且 return 它是它的头部,List.tl 也是一个函数它接受一个列表,但这个 return 是尾巴,而构造函数 _::_ 接受一个值和一个相同类型的值列表。因此,您真的应该查看文档 (https://caml.inria.fr/pub/docs/manual-ocaml/libref/List.html) 以获取有关如何使用函数和构造函数的更多信息。

从这里开始:

let rec drop_last l =
match l with
| [] -> []
| [_] -> [] 
| h::t -> h :: drop_last t ;;

到一个if-statement,你可以这样做:

let rec drop_last l =
  if List.length l <= 1 
  then []
  else List.hd l :: drop_last (List.tl l) ;;

那是因为模式[]检查列表是否为空,所以可以用List.length l = 0代替,[_]检查列表是否有一个元素,所以可以被 List.length l = 1 取代,因为在这两种情况下你 return [],你可以用 List.length l <= 1 加入它们, List.hd 需要一个列出列表的参数,所以它需要应用于 l 来给你头​​部,然后附加到带有尾部的递归调用以创建一个新列表 returned.