我想创建一个从1到n的整数列表。我可以使用range(1,n + 1)在Python中执行此操作,在Haskell中使用:take n(iterate(1+)1)。

对此,什么是正确的OCaml成语?

有帮助吗?

解决方案

我所知道的没有成语,但这是一个使用中缀运算符的相当自然的定义:

# let (--) i j = 
    let rec aux n acc =
      if n < i then acc else aux (n-1) (n :: acc)
    in aux j [] ;;
      val ( -- ) : int -> int -> int list = <fun>
# 1--2;;
- : int list = [1; 2]
# 1--5;;
- : int list = [1; 2; 3; 4; 5]
# 5--10;;
- : int list = [5; 6; 7; 8; 9; 10]

或者, comprehensions语法扩展(提供语法上面的[i .. j] 可能会包含在”社区版“ OCaml ,这可能成为惯用语。如果您不熟悉该语言,我不建议您开始使用语法扩展。

其他提示

包含电池,您可以写

let nums = List.of_enum (1--10);;

- 运算符生成从第一个值到第二个值的枚举。 - ^ 运算符类似,但枚举半开间隔( 1 - ^ 10 将枚举1到9)。

你走了:

let rec range i j = if i > j then [] else i :: (range (i+1) j)

请注意,这不是尾递归。现代Python版本甚至有一个懒惰的范围。

这适用于基础OCaml:

<代码> &#65283; List.init 5(有趣的x - &gt; x + 1);; - :int list = [1; 2; 3; 4; 5]

OCaml在范围上具有模式匹配的特殊语法:

let () =
  let my_char = 'a' in
  let is_lower_case = match my_char with
  | 'a'..'z' -> true (* Two dots define a range pattern *)
  | _ -> false
  in
  printf "result: %b" is_lower_case

要创建范围,您可以使用 Core

List.range 0 1000

如果您使用 open Batteries (这是标准库的社区版本),您可以通过 List执行 range(1,n + 1) .range 1`to n (注意 To 之前的反引号)。

更通用的方法(也需要电池)是使用 List.init nf ,它返回一个包含(f 0)(f 1)...(f(n-1))的列表。

这里的比赛有点晚了,但这是我的实施:

let rec range ?(start=0) len =
    if start >= len
    then []
    else start :: (range len ~start:(start+1))

然后你可以像python函数一样使用它:

range 10 
     (* equals: [0; 1; 2; 3; 4; 5; 6; 7; 8; 9] *)

range ~start:(-3) 3 
     (* equals: [-3; -2; -1; 0; 1; 2] *)

自然我觉得最好的答案就是简单地使用Core,但如果你只需要一个函数并且你试图避免使用完整的框架,这可能会更好。

BTW,在Haskell中你宁愿使用

enumFromTo 1 n
[1 .. n]

这些都是不必要的。

take n [1 ..]
take n $ iterate (+1) 1

从上面跟随Alex Coventry,但更短。

let range n = List.init n succ;;    
> val range : int -> int list = <fun>   
range 3;;                           
> - : int list = [1; 2; 3]              

如果您不需要“步骤”,参数,实现此功能的一种简单方法是:

让范围开始停止= List.init(abs @@停止 - 开始)(有趣的我 - > i +开始)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top