Recursion 递归调用Ocaml上的For循环

Recursion 递归调用Ocaml上的For循环,recursion,ocaml,primes,prime-factoring,Recursion,Ocaml,Primes,Prime Factoring,我正在OCaml中实现素数分解。我不是一个函数式程序员;下面是我的代码。素数分解在素数部分函数中递归发生primes是从0到num的primes列表。这里的目标是我可以在OCaml解释器中键入prime_部分,并在n=20,k=1时将其吐出 2 + 3 + 7 5 + 7 我从OCaml教程中改编了是素数和所有素数所有素数,以生成一个到b的素数列表 (* adapted from http://www.ocaml.org/learn/tutorials/99problems.html *) l

我正在OCaml中实现素数分解。我不是一个函数式程序员;下面是我的代码。素数分解在素数部分函数中递归发生
primes
是从0到num的primes列表。这里的目标是我可以在OCaml解释器中键入prime_部分,并在n=20,k=1时将其吐出

2 + 3 + 7
5 + 7
我从OCaml教程中改编了
是素数
所有素数
<在调用
prime\u part
之前,需要调用code>所有素数,以生成一个到
b
的素数列表

(* adapted from http://www.ocaml.org/learn/tutorials/99problems.html *)
let is_prime n =
    let n = abs n in
    let rec is_not_divisor d =
      d * d > n || (n mod d <> 0 && is_not_divisor (d+1)) in
    n <> 1 && is_not_divisor 2;;

let rec all_primes a b =
  if a > b then [] else
    let rest = all_primes (a + 1) b in
    if is_prime a then a :: rest else rest;;

let f elem =
    Printf.printf "%d + " elem

let rec prime_part n k lst primes =
    let h elem =
        if elem > k then
            append_item lst elem;
        prime_part (n-elem) elem lst primes in
    if n == 0 then begin
        List.iter f lst;
        Printf.printf "\n";
        ()
    end
    else
        if n <= k then
        ()
        else 
            List.iter h primes;
            ();;

let main num = 
    prime_part num 1 [] (all_primes 2 num)

下面是对您的代码的一些注释

  • 您可以在OCaml中定义嵌套函数。嵌套函数可以访问以前定义的所有名称。因此,您可以使用
    List.iter
    ,而不会丢失对局部变量的访问

  • 我看不出函数
    prime\u part\u constructive
    返回整数值的任何原因。在OCaml中,返回值
    ()
    ,即所谓的“unit”,更为惯用。这是因其副作用(如打印值)而调用的函数返回的值

  • 符号
    a.(i)
    用于访问数组,而不是列表。列表和数组在OCaml中不同。如果您将的
    替换为
    List.iter
    ,您就不必担心这一点

  • 要连接两个列表,请使用
    @
    运算符。符号
    lst.concat
    在OCaml中没有意义

  • 更新

    下面是嵌套函数的外观。这个组合函数获取一个数字
    n
    和一个整数列表,然后写出列表中每个元素乘以
    n
    的值

    let write_mults n lst =
        let write1 m = Printf.printf " %d" (m * n) in
        List.iter write1 lst
    
    write1
    函数是一个嵌套函数。请注意,它可以访问
    n
    的值

    let write_mults n lst =
        let write1 m = Printf.printf " %d" (m * n) in
        List.iter write1 lst
    
    更新2

    下面是我编写函数时得到的结果:

    let prime_part n primes =
        let rec go residue k lst accum =
            if residue < 0 then
                accum
            else if residue = 0 then
                lst :: accum
            else
                let f a p =
                    if p <= k then a
                    else go (residue - p) p (p :: lst) a
                in
                List.fold_left f accum primes
        in  
        go n 1 [] []
    
    设素数\u部分n素数=
    让rec走剩余k第一次累计=
    如果剩余<0,则
    累积
    否则,如果剩余=0,则
    累计
    其他的
    设f为p=
    如果p int list->int list list=
    #素数第12部分[2;3;5;7;11];;
    -:int list=[[7;5];[7;3;2]]
    

    请注意,此函数返回分区列表。这比写出来(IMHO)更有用(也更实用)。

    我在原始帖子中编辑了我的OCaml代码,以反映您建议的更改。当我将它放入OCaml解释器时,它正在轰炸函数h,因为它无法访问
    lst
    。它给了我一个
    未绑定值lst
    错误。你知道为什么吗?你的函数
    h
    没有被定义为嵌套函数。如果您想让它访问
    lst
    ,您需要在
    prime\u part\u constructive
    中定义它。我将它移动到函数中(见上文)。但是,解释器说它找不到
    h
    。那是因为我在使用它之前引用了它吗?如果是这样,我如何在不破坏
    prime\u part
    的函数定义的情况下更改它。它仍然不在函数内部,现在它已经超过了另一侧的函数:-)我将编写一个嵌套函数的示例。啊哈!我相信我现在已将其更正为在函数中使用
    in
    操作符。但是,现在我有一个错误
    此表达式的类型为'a->'b list->'c->'d,但表达式的类型应为int
    。当我递归调用
    prime\u part
    时,解释器在
    prime\u part n
    下划线。在函数调用中可以有表达式吗?
    val prime_part : int -> int list -> int list list = <fun>
    # prime_part 12 [2;3;5;7;11];;
    - : int list list = [[7; 5]; [7; 3; 2]]