List OCaml代码说明:分解字符串,拆分列表

List OCaml代码说明:分解字符串,拆分列表,list,recursion,pattern-matching,ocaml,List,Recursion,Pattern Matching,Ocaml,我绝对是OCaml初学者,有一个关于更多代码的作业。我有以下代码,但我不知道它是如何工作的。如果有人能帮我,我很感激 # let explode str = (*defines function that explodes argument str witch is type string into list of chars*) let rec exp = function (*defines recursive function ex

我绝对是OCaml初学者,有一个关于更多代码的作业。我有以下代码,但我不知道它是如何工作的。如果有人能帮我,我很感激

# let explode str =  (*defines function that explodes argument str witch is type
                       string into list of chars*)
  let rec exp = function    (*defines recursive function exp*)
    | a, b when a < 0 -> b  (*this part i dont know.is this pattern 
                              matching ?is it function with arguments a and b
                              and they go into expression? when is a guard and 
                              then we have if a is smaller than 0 then b *)
 (*if a is not smaller than 0 then this function ? *)
    | a, b -> exp (a-1, str.[a]::b) (*this i dont know, a and b are arguments
                                      that go into recursive function in the way
                                      that a is decreesed by one and b goes into
                                      string a?? *)
  in         
  exp ((String.length str)-1, []);; (*defined function exp on string lenght of
                                      str decresed by one (why?)  [ ]these
                                      brackets mean or tell some kind of type ? *)

# let split lst ch =
  let rec split = function  (* defines recursive fun split *)
    | [], ch, cacc', aacc' -> cacc'::aacc'(* if empty ...this is about what i got
                                             so far :) *)
    | c::lst, ch, cacc', aacc' when c = ch -> split (lst, ch, [], cacc'::aacc')
    | c::lst, ch, cacc', aacc' -> split (lst, ch, c::cacc', aacc')
  in
  split (lst, ch, [], []);;

val split : 'a list -> 'a -> 'a list list = <fun>
#让explode str=(*定义分解类型为的参数str的函数
字符串到字符列表*)
设rec exp=function(*定义递归函数exp*)
|a,b当a<0->b(*这部分我不知道。这是模式吗
匹配?它是带有参数a和b的函数吗
他们开始表达了吗?什么时候是警卫和警察
如果a小于0,那么b*)
(*如果a不小于0,则此函数?*)
|a,b->exp(a-1,str.[a]::b)(*这个我不知道,a和b是参数
以这种方式进入递归函数
a由1颁布,b进入
字符串a??*)
在里面
exp((String.length str)-1,[]);;(*字符串长度上定义的函数exp)
str减少1(为什么?[]这些
括号表示或表示某种类型?*)
#让我们把lst和ch分开=
let rec split=函数(*定义递归乐趣拆分*)
|[],ch,cacc',aacc'->cacc'::aacc'(*如果为空…这是我得到的
到目前为止:)*)
|c::lst,ch,cacc',aacc',当c=ch->split时(lst,ch,[],cacc'::aacc')
|c::lst,ch,cacc',aacc'->拆分(lst,ch,c::cacc',aacc')
在里面
拆分(lst、ch、[]、[]);;
val split:'a list->'a->'a list=

这个代码很难看。不管是谁给了你,都是在伤害你。如果我的一个学生写了这篇文章,我会要求他们在不使用条件时重写它们,因为它们容易混淆,鼓励他们在不需要的地方编写模式匹配的重代码。
作为一条经验法则,初学者不应该在时使用
。一个简单的
if..then..else
测试可以提高可读性

以下是这两个函数的等效版本,为可读性而重写:

let explode str =
  let rec exp a b =
    if a < 0 then b
    else exp (a - 1) (str.[a] :: b)
  in
  exp (String.length str - 1) []

let split input delim_char =
  let rec split input curr_word past_words =
    match input with
      | [] -> curr_word :: past_words
      | c :: rest ->
        if c = delim_char
        then split rest [] (curr_word :: past_words)
        else split rest (c :: curr_word) past_words
  in
  split input [] []
对于每个函数,以及您在理解任何函数时遇到的问题,请务必小心。举个小例子。这是了解全球情况的最佳方式


(稍后,当你越来越习惯递归时,你会发现你实际上不需要这样做,你可以对函数进行归纳推理:假设它们做了什么,假设递归调用确实做了,检查它是否真的做了。在更高级的情况下,试图将所有的执行都控制在自己的头脑中是非常困难的这种归纳技术工作得更好,但它更高级,需要更多的实践

这段代码很难看。无论是谁给了你这段代码,都是在伤害你。如果我的一个学生写了这段代码,我会要求他们在不使用
条件时重写它们,因为它们容易混淆,鼓励他们在没有保证的地方编写模式匹配的重代码。
作为一条经验法则,初学者不应该在时使用
。一个简单的
if..then..else
测试可以提高可读性

以下是这两个函数的等效版本,为可读性而重写:

let explode str =
  let rec exp a b =
    if a < 0 then b
    else exp (a - 1) (str.[a] :: b)
  in
  exp (String.length str - 1) []

let split input delim_char =
  let rec split input curr_word past_words =
    match input with
      | [] -> curr_word :: past_words
      | c :: rest ->
        if c = delim_char
        then split rest [] (curr_word :: past_words)
        else split rest (c :: curr_word) past_words
  in
  split input [] []
对于每个函数,以及任何你在理解上有问题的函数,都要小心这样做。举个小例子。这是获得全局视图的最佳方法


(稍后,当你越来越习惯递归时,你会发现你实际上不需要这样做,你可以对函数进行归纳推理:假设它们做了什么,假设递归调用确实做了,检查它是否真的做了。在更高级的情况下,试图将所有的执行都控制在自己的头脑中是非常困难的rd,这种归纳技术工作得更好,但它更高级,需要更多的实践。首先,只需运行代码即可。)

您也可以用这种方式实现

let rec strexp s  =  
  if length(s)==0 then 
   []
  else
  (strexp (sub s 0 (length(s)-1)))@(s.[length(s)-1]::[])    
;;

您也可以通过这种方式实现

let rec strexp s  =  
  if length(s)==0 then 
   []
  else
  (strexp (sub s 0 (length(s)-1)))@(s.[length(s)-1]::[])    
;;

如果您使用的是核心库,那么只需使用

String.to_list "BKMGTPEZY"
如果您想要字符串映射,它将返回
字符列表

String.to_list "BKMGTPEZY" |> List.map ~f:Char.to_string
产出:

- : bytes list = ["B"; "K"; "M"; "G"; "T"; "P"; "E"; "Z"; "Y"]
作为一项功能

let explode s = String.to_list s |> List.map ~f:Char.to_string

如果您使用的是核心库,那么只需使用

String.to_list "BKMGTPEZY"
如果您想要字符串映射,它将返回
字符列表

String.to_list "BKMGTPEZY" |> List.map ~f:Char.to_string
产出:

- : bytes list = ["B"; "K"; "M"; "G"; "T"; "P"; "E"; "Z"; "Y"]
作为一项功能

let explode s = String.to_list s |> List.map ~f:Char.to_string

为什么不先在代码中添加注释,解释您已经理解的内容,并指出您不理解的部分?为什么不先在代码中添加注释,解释您已经理解的内容,并指出您不理解的部分?谢谢您的回答。您非常好。我会知道您的想法谢谢你的回答,你真是太好了。我会知道你的建议的