0

我刚刚开始学习 ocaml,我发现很难从更大的字符列表中提取小字符列表。

假设我有:

let list_of_chars = ['#' ; 'a' ; 'b' ; 'c'; ... ; '!' ; '3' ; '4' ; '5' ];;

我有以下知识 - 我知道在上面的列表中我有 '#' 后跟一个 '!' 在列表中的某个位置。

我想提取列表 ['a' ;'b' ;'c' ; ...] 和 ['3' ; '4' ; '5'] 并对他们做一些事情,所以我做了以下事情:

let variable = match list_of_chars with 
| '#'::l1@['!']@l2 -> (*[code to do something with l1 and l2]*)
| _ ->  raise Exception ;;

这段代码对我不起作用,它会引发错误。有没有一种简单的方法可以做到这一点?

(专门用于使用匹配)

4

2 回答 2

2

正如另一个答案指出的那样,您不能为此使用模式匹配,因为模式匹配仅允许您使用构造函数而@不是构造函数。

这是您解决问题的方法

let split ~equal ~on list =
  let rec go acc = function
    | [] -> None
    | x::xs -> if equal x on then Some (rev acc, xs) else go (x::acc) xs
  in
  go [] list

let variable = match list_of_chars with
  | '#'::rest ->
    match split rest ~on:'!' ~equal:(Char.equal) with
    | None -> raise Exception 
    | Some (left,right) ->
      ... (* your code here *)

我现在假设您正在尝试进行某种解析或词法分析。我建议您不要使用chars 列表来执行此操作。事实上,我认为几乎没有理由char在 ocaml 中包含 s 列表:astring更适合字符串(achat list在内存使用方面的开销是 23 倍),而在 C 中可能会使用 chars 作为一种助记符枚举, ocaml 具有实际的枚举(也称为变体类型或总和类型),因此通常应该使用它们。chat list我想如果你用 trie 做某事,你最终可能会得到 a 。

如果您对解析或词法分析感兴趣,您可能需要研究:

  1. Ocamllex 和 ocamlyacc
  2. 赛德克斯
  3. Angstrom 或其他类似的解析器生成器
  4. 正则表达式库之一(例如 Re、Re2、Pcre(注意 Re 和 Re2 大多不相关)
  5. 使用字符串和函数,如 lsplit2
于 2019-11-30T12:43:40.097 回答
1

@是一个运算符,而不是一个有效的模式。模式需要是静态的,并且不能匹配列表中间的不同数量的元素。但是既然你知道!它的位置不需要是动态的。您可以使用以下方法完成它::

let variable = match list_of_chars with 
| '#'::a::b::c::'!'::l2 -> let l1 = [a;b;c] in ...
| _ ->  raise Exception ;;
于 2019-11-28T20:00:34.107 回答