ocaml递归模式匹配

REA*_*EE 7 ocaml matching

我正在尝试编写一个简单的递归函数,它查看列表并返回一对整数.这很容易用c/c ++/java编写,但我是ocaml的新手,所以由于类型冲突很难找到解决方案

它应该像..

let rec test p l = ... ;;
val separate : (’a -> bool) -> ’a list -> int * int = <fun>
test (fun x -> x mod 2 = 0) [-3; 5; 2; -6];; 
- : int * int = (2, 2)
Run Code Online (Sandbox Code Playgroud)

所以问题是我如何递归返回元组的值..

dan*_*ben 5

这里的一个问题是你返回两种不同的类型:一个是空列表的int,另一个是元组.它需要是一个或另一个.

另一个问题是你试图添加1 test,但它test是一个函数,而不是一个值.你需要在其他东西上调用test才能返回一个值,但即使这样它也应该返回一个元组,你不能将它添加到一个整数中.

我无法弄清楚你想要代码做什么,但如果你用这些信息更新你的问题,我可以提供更多帮助.

我猜的是你想要计算列表中的正数,在这种情况下你可以像这样写:

let rec test l = 
    match l with [] -> 0
   | x::xs -> if x > 0 then 1 + (test xs)
              else test xs;;
Run Code Online (Sandbox Code Playgroud)

更新:既然您已编辑以澄清问题,请按以下方式修改上述代码:

let test l =
  let rec test_helper l pos nonpos = 
    match l with [] -> (pos, nonpos)
   | x::xs -> if x > 0 then test_helper xs 1+pos, nonpos
              else test_helper xs pos 1+nonpos
  in test_helper l 0 0;;
Run Code Online (Sandbox Code Playgroud)

在这种情况下,使用累加器有很大帮助.它还使函数tail-recursive,这总是很好的做法.


gog*_*n13 4

离开 OCaml 有一段时间了,但我认为这对于评论中 REALFREE 的描述会起到作用

let rec test l = 
  match l with 
      [] -> (0,0) 
    | x::xs -> 
        if x > 0 then match (test xs) with (x,y) -> (x+1, y)
        else  match (test xs) with (x,y) -> (x, y+1);;
Run Code Online (Sandbox Code Playgroud)

您可以使用嵌套的匹配语句来提取元组的各个部分以进行修改

编辑:我不知道 Pascal Cuoq 在下面的评论中提到的语法,这是这样的代码,它更简洁,更短:

let rec test l = 
  match l with 
      [] -> (0,0) 
    | x::xs -> 
    if x > 0 then let (x,y) = test xs in (x+1, y)
    else let (x,y) = test xs in (x, y+1);;
Run Code Online (Sandbox Code Playgroud)

但接受的答案仍然要好得多,尤其是尾递归;)。

  • 如果您正在使用单个模式编写“match .. with ..”,则可以使用“let”来代替:“let x, y = test xs in ...” (2认同)