我正在尝试编写一个简单的递归函数,它查看列表并返回一对整数.这很容易用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)
所以问题是我如何递归返回元组的值..
这里的一个问题是你返回两种不同的类型:一个是空列表的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,这总是很好的做法.
离开 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)
但接受的答案仍然要好得多,尤其是尾递归;)。