代码之家  ›  专栏  ›  技术社区  ›  Pramod

ocaml的习惯用法与python的range函数等价吗?

  •  22
  • Pramod  · 技术社区  · 17 年前

    我想创建一个从1到n的整数列表。我可以在python中使用range(1,n+1),在haskell中使用:take n(iterate(1+)1。

    正确的OCAML习惯用法是什么?

    9 回复  |  直到 7 年前
        1
  •  24
  •   Charles Duffy    13 年前

    我不知道有什么成语,但这里有一个使用中缀运算符的相当自然的定义:

    # 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 从而可能成为惯用语。不过,如果您不熟悉该语言,我不建议您开始使用语法扩展。

        2
  •  13
  •   Michael Ekstrand    15 年前

    Batteries Included 你可以写

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

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

        3
  •  11
  •   Matthias    15 年前

    干得好:

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

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

        4
  •  3
  •   Matthias Braun AdamSkywalker    10 年前

    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
  •   user69818    11 年前

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

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

        6
  •  2
  •   JustGage    9 年前

    这里的游戏有点晚了,但我的实现是:

    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] *)
    

    当然,我认为最好的答案是简单地使用核心,但是如果您只需要一个函数,并且试图避免使用完整的框架,那么这可能会更好。

        7
  •  2
  •   Alex Coventry    7 年前

    这在基本OCAML中有效:

    # List.init 5 (fun x -> x + 1);; - : int list = [1; 2; 3; 4; 5]

        8
  •  1
  •   ephemient    17 年前

    顺便说一句,在哈斯克尔你宁愿用

    enumFromTo 1 n
    [1 .. n]
    

    这些都是不必要的。

    take n [1 ..]
    take n $ iterate (+1) 1
    
        9
  •  0
  •   rdavison    7 年前

    如果不需要“step”参数,实现此函数的一个简单方法是:

    let range start stop = List.init (abs @@ stop - start) (fun i -> i + start)

    推荐文章