Recursion 用于在OCaml中重复字符串的递归函数

Recursion 用于在OCaml中重复字符串的递归函数,recursion,ocaml,Recursion,Ocaml,我绝对是OCaml初学者。我想创建一个重复字符20次的函数。 这是函数,但由于错误而无法工作 let string20 s = let n = 20 in s ^ string20 s (n - 1);; string20 "u";; 我想这样跑 # string20 "u" - : string = "uuuuuuuuuuuuuuuuuuuu" 函数string20接受一个参数,但使用两个参数递归调用 基本思想在那里,但形式不太正确。一种方法是将2参数函数作为单独的“助手”函数分

我绝对是OCaml初学者。我想创建一个重复字符20次的函数。 这是函数,但由于错误而无法工作

let string20 s =
  let n = 20 in
  s ^ string20 s (n - 1);;

string20 "u";;
我想这样跑

# string20 "u"
- : string = "uuuuuuuuuuuuuuuuuuuu"

函数
string20
接受一个参数,但使用两个参数递归调用

基本思想在那里,但形式不太正确。一种方法是将2参数函数作为单独的“助手”函数分离出来。正如@PierreG所指出的,您需要将helper函数作为递归函数进行delcare

  • Ocaml中的递归函数是用
    let rec
  • 正如在注释中指出的那样,您已经将函数定义为接受一个参数,但尝试使用两个参数递归调用
  • 你可能想要像这样的东西


    将函数分为“固定”部分和归纳部分是一种常见的模式。在这种情况下,需要一个嵌套的helper函数来在新范围内执行真正的递归工作,同时我们要将输入字符串
    s
    固定为常量,以便我们可以使用它附加到
    s2
    s2
    是一个累加器,随着时间的推移形成串,而
    c
    是一个朝着基本情况向下计数至1的电感器

    let repeat s n = 
      let rec helper s1 n1 = 
        if n1 = 0 then s1 else helper (s1 ^ s) (n1 - 1)
      in helper "" n
    
    非尾部调用版本更简单,因为您根本不需要助手函数:

    let rec repeat s n = 
      if n = 0 then "" else s ^ repeat s (n - 1)
    
    另一方面,关于一种具有像Ocaml这样的一流函数的函数式语言,有一件非常有趣的事情就是curry(或部分应用程序)。在这种情况下,您可以创建一个名为
    repeat
    的函数,该函数接受类型为
    int
    n
    和类型为
    string
    s
    两个参数,并将其部分应用于
    n
    s
    ,如下所示:

    # (* top-level *)
    # let repeat_foo = repeat "foo";;
    # repeat_foo 5;;
    - : bytes = "foofoofoofoofoo"   (* top-level output *)
    
    如果
    n
    参数标记如下:

    let rec repeat ?(n = 0) s = 
          if n = 0 then "" else s ^ repeat s (n - 1)
    
    可以利用应用程序的顺序,使功能更加灵活:

    # (* top-level *)
    # let repeat_10 = repeat ~n:10;;
    # repeat_10 "foo";;
    - : bytes = "foofoofoofoofoofoofoofoofoofoo" (* top-level output *)
    

    请参阅我的帖子(虽然它是用JavaScript编写的,但很容易理解)。您应该首先考虑递归函数的停止条件。然后,您应该知道在ocaml中声明递归函数时应用的语法(这是ocaml课程级别)。您能输入收到的错误吗?有点离题,但
    String.make 20'u'
    可以完成此任务。
    string20
    接受单个参数
    s
    ,但是在第二次通话和之后提供了
    s
    n-1
    。您将此问题编辑得面目全非,因此我将其回滚,因为原始问题有几个很好的答案。命名
    stringn
    是非常多余的,由于Ocaml函数是curry函数,您可以执行类似于
    let stringN=string N in stringN“foo”
    的操作,您上面的函数是一个无限递归,因为没有基本情况,而且
    N
    永远不会减少。@PieOhPah。感谢我错过了(n-1)。要真正工作,您的尾部递归
    助手
    应该最好在基本情况下返回
    s2
    ,并使用
    而不是
    s
    调用。而且,
    s1
    是冗余的。您上一个示例中的标签
    ~n
    来自哪里?@AndreasRossberg是的,谢谢您的更正。为了更清晰,我还添加了带标签的参数版本。我相信对
    helper
    的调用仍然是错误的。您需要使用空字符串调用它,否则您将被取消1。
    let rec repeat ?(n = 0) s = 
          if n = 0 then "" else s ^ repeat s (n - 1)
    
    # (* top-level *)
    # let repeat_10 = repeat ~n:10;;
    # repeat_10 "foo";;
    - : bytes = "foofoofoofoofoofoofoofoofoofoo" (* top-level output *)