我绝对是OCaml初学者。我想创建一个重复字符20次的函数。 这是函数,但由于错误而无效。
let string20 s =
let n = 20 in
s ^ string20 s (n - 1);;
string20 "u";;
我想像这样跑
# string20 "u"
- : string = "uuuuuuuuuuuuuuuuuuuu"
答案 0 :(得分:1)
你的函数string20
有一个参数,但是你用2个参数递归调用它。
基本的想法在那里,但不是很正确的形式。一种方法是将2参数函数分离为单独的"帮助"功能。正如@PierreG指出的那样,你需要将辅助函数作为递归函数进行delcare。
答案 1 :(得分:0)
let rec
你可能想要像
这样的东西
let rec stringn s n =
match n with
1 -> s
| _ -> s ^ stringn s (n - 1)
;;
答案 2 :(得分:0)
let rec string n s =
if n = 0 then "" else s ^ string (n - 1) s
let string20 = string 20
答案 3 :(得分:0)
将函数分成" fixed"是一种常见的模式。部分和归纳部分。在这种情况下,需要一个嵌套的辅助函数来在新范围内进行真正的递归工作,同时我们想要将输入字符串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
的函数,该函数接受两个类型为n
int
的{{1}}和类型为s
的{{1}},并将其部分应用于这样的string
或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)
请参阅我的帖子Currying Exercise in JavaScript(虽然它在JavaScript中,但很容易理解)和lambda calculus primer。