我想创建一个从1到n的整数列表。我可以使用range(1,n + 1)在Python中执行此操作,在Haskell中使用:take n(iterate(1+)1)。
对此,什么是正确的OCaml成语?
答案 0 :(得分:25)
我所知道的没有成语,但这是一个使用中缀运算符的相当自然的定义:
# 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 syntax extension(为上面提供语法[i .. j]
)很可能会包含在"community version" of OCaml的未来版本中,因此可能会成为惯用语。如果您不熟悉该语言,我不建议您开始使用语法扩展。
答案 1 :(得分:13)
使用Batteries Included,您可以写
let nums = List.of_enum (1--10);;
--
运算符生成从第一个值到第二个值的枚举。 --^
运算符类似,但枚举半开区间(1--^10
将枚举1到9)。
答案 2 :(得分:11)
你走了:
let rec range i j = if i > j then [] else i :: (range (i+1) j)
请注意,这不是尾递归。现代Python版本甚至有一个懒惰的范围。
答案 3 :(得分:4)
这适用于基础OCaml:
# List.init 5 (fun x -> x + 1);;
- : int list = [1; 2; 3; 4; 5]
答案 4 :(得分:3)
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
答案 5 :(得分:2)
如果您使用open Batteries
(这是标准库的社区版本),您可以range(1,n+1)
List.range 1 `To n
(注意To
之前的反引用)。< / p>
更通用的方法(也需要电池)是使用List.init n f
返回包含(f 0)(f 1)...(f(n-1))的列表。
答案 6 :(得分:2)
这里的比赛有点晚了,但这是我的实施:
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,但如果你只需要一个函数并且你试图避免使用完整的框架,这可能会更好。
答案 7 :(得分:1)
BTW,在Haskell中你宁愿使用
enumFromTo 1 n
[1 .. n]
这些都是不必要的。
take n [1 ..]
take n $ iterate (+1) 1
答案 8 :(得分:1)
从上方跟随Alex Coventry,但更短。
category_id
答案 9 :(得分:1)
如果您打算模拟range
的惰性行为,我实际上建议您使用Stream
模块。像这样:
let range (start: int) (step: int) (stop: int): int stream =
Stream.from (fn i -> let j = i * step + start in if j < stop then Some j else None)
答案 10 :(得分:0)
如果你不需要&#34;步骤&#34;参数,实现此功能的一种简单方法是:
let range start stop = List.init (abs @@ stop - start) (fun i -> i + start)
答案 11 :(得分:0)
对此表示敬意:
let range a b =
List.init (b - a) ((+) a)
答案 12 :(得分:0)
过时的我为此使用ocaml的范围库
(* print sum of all values between 1 and 50, adding 4 to all elements and excluding 53 *) Range.(from 1 50 |> map ((+) 4) |> filter ((!=) 53) |> fold (+) 0 |> print_int);;