OCaml 中函数组合的尾递归版本

Jac*_*ale 5 ocaml

非尾递归组合函数可以这样写:

let rec combinations l k =
  if k <= 0 || k > List.length l then []
  else if k = 1 then List.map (fun x -> [x]) l 
  else 
    let hd, tl = List.hd l, List.tl l in
    combinations tl k |> List.rev_append (List.map (fun x -> hd::x) (combinations tl (k-1)))
Run Code Online (Sandbox Code Playgroud)

请注意,我List.rev_append至少使用append了尾递归版本

这意味着如果您想从列表中取出 k 个元素,则生成所有组合。

我只是想知道是否有可能创建一个完整的尾递归版本combinations

phi*_*mue 0

您可以使用连续传递样式

let combos l k =
    let rec aux l k cont =
        if k <= 0 || k > List.length l then cont []
        else if k = 1 then cont (List.map (fun x -> [x]) l)
        else 
            let hd, tl = List.hd l, List.tl l in
            aux tl k 
            (
                fun res1 -> aux tl (k-1)
                (
                    fun res2 -> cont (List.rev_append (List.map (fun x -> hd::x) res2) res1)
                )
            )
    in aux l k (fun x -> x)
Run Code Online (Sandbox Code Playgroud)

这样,您就可以避免在递归调用之后调用某些内容,aux代价是创建一个匿名函数,该函数负责在“原始递归调用”之后完成的“未来计算”。