Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
OCaml中函数组合的尾部递归版本_Ocaml - Fatal编程技术网

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

OCaml中函数组合的尾部递归版本,ocaml,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

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

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)))
让rec组合l k=
如果k List.length l,则[]
否则,如果k=1,则List.map(fun x->[x])l
其他的
让hd,tl=List.hd l,List.tl l进入
组合tl k |>List.rev_append(List.map(funx->hd::x)(组合tl(k-1)))
请注意,我使用了
List.rev_append
,至少给定了
append
一个尾部递归版本

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

我只是想知道是否有可能创建一个总尾部递归版本的
组合

您可以使用:

让组合Lk=
让rec aux l k cont=
如果k列表长度为l,则继续[]
否则,如果k=1,则继续(List.map(fun x->[x])l)
其他的
让hd,tl=List.hd l,List.tl l进入
辅助TLK
(
乐趣res1->辅助tl(k-1)
(
fun res2->cont(List.rev_append(List.map(fun x->hd::x)res2)res1)
)
)
在辅助LK(乐趣x->x)

这样,您就可以避免在递归调用
aux
之后调用某个函数,而代价是创建一个匿名函数,该函数用于解释“原始递归调用”之后将要进行的“未来计算”。

通常我们会采用延续传递方式,如Phimueme的回答。例如

let rec prefix_cps tree k =
  match tree with
  | Tip -> k []
  | Node (left,n,right) ->
    prefix_cps left (fun nleft ->
        prefix_cps right (fun nright ->
            k (n :: nleft @ nright)))
let prefix_cps t = prefix_cps t (fun l -> l)
但是,有时我们可以动态地重新安排输入:

let rec prefix_tr t =
  let rec loop queue = function
    | Tip -> queue
    | Node (l, n, Tip) -> loop (n::queue) l
    | Node (l, k, Node (rl, n, rr)) ->
      loop queue (Node (Node (l, k, rl), n, rr)) in
  loop [] t

还有其他更自然的方法吗?@JacksonTale这正是我问自己的,我不得不说我不确定。但是从我(承认是非常有限的)经验来看,如果您的原始函数依赖于多个递归调用,那么编写相应的尾部递归版本通常是很麻烦的。您能给出更多的解释吗?什么是
提示
,算法是什么?这是生成组合吗?不,这是树的前缀遍历:
type'a tree=Tip | Node of'a tree*'a*'a tree
——这不适用于组合,只是我决定在这里加上的一般性注释。
let rec prefix_tr t =
  let rec loop queue = function
    | Tip -> queue
    | Node (l, n, Tip) -> loop (n::queue) l
    | Node (l, k, Node (rl, n, rr)) ->
      loop queue (Node (Node (l, k, rl), n, rr)) in
  loop [] t