嘿,任何人都可以帮助我在 OCaml 中创建一个函数,该函数将接受一个字符串并递归地返回带有 less 和字母的字符串。我正在尝试使用子字符串和递归来完成此任务,有什么想法可以为我指明正确的方向吗?
String
Strin
Stri
Str
St
S
我使用了 LISP 并创建了
car
和 cdr
函数
let car = function
| [] -> raise Not_found
| first :: _ -> first
and cdr = function
| [] -> raise Not_found
| _ :: rest -> rest
您想使用 Jeffrey
提到的
String.sub
函数。
如果您希望 "String"
成为:
String
Strin
Stri
Str
St
S
您需要:
String.sub "String" 0 6
String.sub "String" 0 5
String.sub "String" 0 4
String.sub "String" 0 3
String.sub "String" 0 2
String.sub "String" 0 1
只有一个参数发生变化:子字符串的长度。如果您想要逐渐缩短字符串,您只需要逐渐缩短长度。
假设您可以递归地生成这些值,您只需要:
let substrings s =
let lengths = ... in
lengths |> List.map (String.sub s 0)
或者,我们可以将字符串转换为序列,然后使用左折叠的替代形式,将中间初始值存储为列表。
类似于 Haskell 的 scanl
# let[@tail_mod_cons] rec seq_acc_fold_left f init seq =
match seq () with
| Seq.Nil -> [init]
| Seq.Cons (v, seq') ->
let init' = f init v in
init' :: seq_acc_fold_left f init' seq';;
val seq_acc_fold_left : ('a -> 'b -> 'a) -> 'a -> 'b Seq.t -> 'a list = <fun>
实现了这个简单的函数后,我们只需将函数调用链接在一起即可。
# "String"
|> String.to_seq
|> Seq.map @@ String.make 1
|> seq_acc_fold_left (^) "";;
- : string list = ["S"; "St"; "Str"; "Stri"; "Strin"; "String"; "String"]
在我看来,直接使用字符串比转换为字符列表更有意义。您可以使用 String.sub 来创建一个新字符串,该新字符串是另一个字符串的子字符串。例如:
# let s = "example" in String.sub s 0 (String.length s - 1);;
- : string = "exampl"
如果你想返回越来越短的字符串列表,你可以编写一个递归函数。您的函数(实质上)会将完整字符串添加到通过在较短的字符串上递归调用自身而创建的列表的头部。我不再多说了,因为弄清楚递归是如何工作的并欣赏它的表达能力是人们学习 OCaml 这样的函数式语言的原因之一。
我希望这对你有帮助