在ocaml中构建一个int列表

时间:2011-04-13 18:21:47

标签: list ocaml int

我想编写一个函数来构建两个整数之间的列表,包括

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运算符是有效的,但它说它应该是无效的?

为什么会发生这种情况,我该如何解决?

5 个答案:

答案 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; ...]