将F#seq表达式转换为OCaml

时间:2013-01-20 19:33:59

标签: f# ocaml

在我试图转换为OCaml的F#代码中,我遇到了以下内容:

    let rec parseList lst off =
        seq {
            if List.isEmpty lst then ()
            else
                match parse off <| List.head lst with
                | (Unmatched, _) as y -> yield y
                | (y, z) -> yield (y, z)
                            yield! parseList (List.tail lst) z
        }

我想知道如何将 seq {...} 表达式与 yield 转换为OCaml?我的第一个猜测是 seq 必须成为一个列表。

3 个答案:

答案 0 :(得分:5)

最简单的翻译(不是尾递归)是:

let rec parseList lst off =
  match lst with
  | [] -> []
  | x::xs ->
      match parse off x with
      | Unmatched, _ as y -> [y]
      | y, z -> (y, z)::parseList xs z

尾递归版是:

let parseList lst off =
  let rec loop xs off = function
    | [] -> xs
    | y::ys ->
        match parse off y with
        | Unmatched, _ as x -> x::xs
        | _, z as x -> loop (x::xs) z ys in
  List.rev (loop [] off lst)

请注意,您开始使用的F#代码有很多不足之处。当您可以更轻松地使用模式匹配时,对List.headList.tail的调用是不必要的潜在异常来源。并且有多余的括号。

答案 1 :(得分:3)

我会说seq是一个惰性列表,即一个列表,其尾部是在需要时计算的,而不是一次性计算的。 OCaml中最接近的东西可能是流解析器,可通过camlp4获得扩展。它记录在OCaml手册的Language Extensions部分中。

您还可以使用fun () -> expr创建自己的显式懒惰列表工具,以表示列表的尾部。

如果您的列表相当小,您也可以按照建议转换为普通列表。

答案 2 :(得分:2)

我会看一下电池中的LazyList.fromhttp://ocaml-batteries-team.github.com/batteries-included/hdoc2/BatLazyList.html

但是,我认为它不如您的解决方案那么方便。