我正在尝试编写一个简单的递归函数,它查看列表并返回一对整数。这很容易用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)
所以问题是我怎么能递归地返回元组上的值..
答案 0 :(得分:5)
这里的一个问题是你返回两种不同的类型:一个是空列表的int,另一个是元组。它必须是一个或另一个。
另一个问题是您尝试向test
添加1,但test
是一个函数,而不是值。你需要在其他东西上调用test来返回一个值,但即使这样它也应该返回一个元组,你不能将它添加到一个整数。
我无法弄清楚您希望代码执行什么操作,但如果您使用该信息更新问题,我可以提供更多帮助。
我猜的是你想要计算列表中的正数,在这种情况下你可以这样写:
let rec test l =
match l with [] -> 0
| x::xs -> if x > 0 then 1 + (test xs)
else test xs;;
更新:由于您已编辑以澄清问题,请按以下步骤修改上述代码:
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;;
在这种情况下,使用累加器可以提供很多帮助。它还使函数tail-recursive,这总是很好的做法。
答案 1 :(得分: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);;
您可以使用嵌套的匹配语句来提取元组的片段以进行修改
编辑: 我不知道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);;
但是接受的答案仍然要好得多,尤其是尾部递归;)。