我是绝对的OCaml初学者。我想创建一个重复20次字符的函数。 这是功能,但由于错误而无法使用。在OCaml中重复字符串的递归函数
let string20 s =
let n = 20 in
s^string20 s (n - 1);;
string20 "u";;
我想这样
# string20 "u"
- : string = "uuuuuuuuuuuuuuuuuuuu"
我是绝对的OCaml初学者。我想创建一个重复20次字符的函数。 这是功能,但由于错误而无法使用。在OCaml中重复字符串的递归函数
let string20 s =
let n = 20 in
s^string20 s (n - 1);;
string20 "u";;
我想这样
# string20 "u"
- : string = "uuuuuuuuuuuuuuuuuuuu"
你的功能string20
运行需要一个参数,但你有两个参数的递归调用它。
基本的想法在那里,但不是正确的形式。继续进行的一种方法是将2参数函数分离为单独的“帮助”函数。正如@PierreG指出的那样,您需要将辅助函数作为递归函数进行修改。 OCaml中
let rec string n s =
if n = 0 then "" else s^string (n - 1) s
let string20 = string 20
这是一个功能分为“固定”部分和感性部分的通用模式。在这种情况下,我们需要一个嵌套帮助函数来在新范围内进行真正的递归工作,同时我们要将输入字符串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这样的类函数是currying(或部分应用程序)。在这种情况下,你可以创建一个名为repeat
函数有两个参数int
型n
和如上,部分应用到任何n
或s
这样string
类型的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 *)
查看我的帖子Currying Exercise in JavaScript(尽管它在JavaScript中,但很容易遵循)和这个lambda calculus primer。
为了实际工作,你的尾递归“帮助器”应该更好地在基本情况下返回's2',并用''“'而不是's'来调用。另外,'s1'是多余的。你最后一个例子中的标签'〜n'从哪里来? –
@AndreasRossberg是的,谢谢你的更正。为了更清晰,我还添加了标签参数版本。 – PieOhPah
我相信对'helper'的调用仍然是错误的。你需要用空字符串来调用它,否则你就会关闭一个。 –
您应该首先考虑递归函数的停止条件。然后,你应该知道在ocaml中应用的语法来声明一个递归函数(这是ocaml课程级别)。 –
你能否把你收到的错误放进去? – AlexKoren
关闭主题,但'String.make 20'u''完成这项工作。 – camlspotter