我想编写一个函数来构建两个整数之间的列表,包括
rec myFunc x y将构建一个包含x和y之间所有整数的列表,包括x和y
对于现在的逻辑,我有类似的东西:
let rec buildList i n = let x = i+1 in if i <= n then i::(buildList x n)
但是这给了我一个错误“Expression has type”一个列表但是表达式需要单位类型。
我认为buildList返回一个int列表,而我作为一个int,所以cons运算符是有效的,但它说它应该是无效的?
为什么会发生这种情况,我该如何解决?
答案 0 :(得分:7)
如果条件为真,则返回列表i::(buildList x n)
。如果不是这样,你会回报什么?
将else []
添加到您的函数以在不满足条件时返回空列表。
当您没有else
时,编译器会认为它是else ()
(因此出现错误消息)。
答案 1 :(得分:3)
您的if
缺少else
条件
我建议您使用尾递归函数:
let buildList x y =
let (x,y) = if x<y then (x,y) else (y,x) in
let rec aux cpt acc =
if cpt < x then acc
else aux (cpt-1) (cpt::acc)
in aux y []
首先,确保你正确地命名了你的边界(防止白痴),然后构建列表,感谢一个带有累加器的本地递归函数。
答案 2 :(得分:1)
两种依赖电池包装的替代方案,
使用展开,目的是建立列表,
let range ~from:f ~until:u =
BatList.unfold f (function | n when n <= u -> Some (n, succ n) | _ -> None)
使用Enum,允许使用惰性数据结构,
# BatList.of_enum @@ BatEnum.(1--9);;
- : int list = [1; 2; 3; 4; 5; 6; 7; 8; 9]
答案 3 :(得分:0)
我的建议,这尊重论证的顺序。
let rec iota n m =
let oper = if n < m then succ else pred in
if n = m then [n] else n :: iota (oper n) m
修改强>
运算符选择在递归部分内部,最好是在这样的外部:
let iota n m =
let oper = if n < m then succ else pred in
let rec f1 n m = if n = m then [n] else n :: f1 (oper n) m in
f1 n m
超过200000个元素我得到了堆栈溢出(所以我们在这里)
# iota 0 250000;;
Stack overflow during evaluation (looping recursion?).
Todo:尾递归
答案 4 :(得分:0)
let buildList i n =
let rec aux acc i =
if i <= n then
aux (i::acc) (i+1)
else (List.rev acc)
in
aux [] i
测试:
# buildList 1 3;;
- : int list = [1; 2; 3]
# buildList 2 1;;
- : int list = []
# buildList 0 250000;;
- : int list =
[0; 1; 2; 3; .... 296; 297; 298; ...]