1

我是绝对的 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>
4

3 回答 3

4

这段代码很难看。谁一直给你这些都是在伤害你。如果我的一个学生这样写,我会要求他们在不使用when条件的情况下重写它们,因为它们往往会令人困惑,鼓励在不需要的地方编写大量模式匹配的代码。
根据经验,初学者永远不应该使用when. 一个简单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 [] []

我对理解它们的建议是在给定的例子上,在纸上自己运行它们。只需写下函数调用(例如explode "foo"and split 'b' ['a';'b';'c';'d']),扩展定义,评估代码以获得另一个表达式等,直到得到结果。这是一个例子:

explode "fo"
=>
exp (String.length "fo" - 1) []
=>
exp 1 []
=>
if 1 < 0 then [] else exp 0 ("fo".[1] :: [])
=>
exp 0 ("fo".[1] :: [])
=>
exp 0 ('o' :: [])
=>
exp 0 ['o']
=>
if 0 < 0 then ['o'] else exp (-1) ("fo".[0] :: ['o'])
=>
exp (-1) ("fo".[0] :: ['o'])
=>
exp (-1) ('f' :: ['o'])
=>
exp (-1) ['f'; 'o']
=>
if -1 < 0 then ['f'; 'o'] else exp (-2) ("fo".[-1] :: ['o'])
=>
['f'; 'o']

对于每个功能以及您将有问题理解的任何功能,请注意这样做。举个小例子。这是获得全球视野的最佳方式。

(后来当你越来越习惯递归时,你会发现你实际上并不需要这样做,你可以对函数进行归纳推理:假设它们做了什么,并假设递归调用实际上是这样做的,检查它确实做到了。在更高级的情况下,试图将所有执行都放在脑海中太难了,这种归纳技术效果更好,但它更高级,需要更多练习。首先从简单开始运行代码。)

于 2012-05-14T13:06:18.440 回答
1

如果您使用的是核心库,则可以使用

String.to_list "BKMGTPEZY"

chars如果您只想要字符串,它将返回一个列表map

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
于 2015-04-05T23:24:45.353 回答
0

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

let rec strexp s  =  
  if length(s)==0 then 
   []
  else
  (strexp (sub s 0 (length(s)-1)))@(s.[length(s)-1]::[])    
;;
于 2014-04-10T14:50:08.830 回答