我可以在不使用递归的情况下截断OCaml中给定元素之后的列表吗?
let truncate (elt: 'a) (q: 'a queue) : unit =
我可以想到如何使用嵌套模式匹配来实现这一目标...寻找一种没有rec的更好方法
答案 0 :(得分:0)
列表节点包含所有下一个元素。
因此,要截断列表,您需要创建一个仅包含第一个元素的新列表(这是获取所需截断列表的唯一方法)。
因此,您正在寻找的函数类型是
let truncate : 'a -> 'a list -> 'a list
= fun elt queue -> ...
正如Jeffrey Scofield所说,避免递归毫无意义。
答案 1 :(得分:0)
当然,如果你真的想要,你可以做很多事情。有两个技术避免递归的例子,然后我认为你可能实际上一直在寻找:
let truncate1 elt list = (* tedious iteration version *)
let list = ref list in
let r = ref [] in
while !list <> [] do
r := List.hd !list :: !r;
if List.hd !list = elt then list := [] else
list := List.tl !list
done;
List.rev !r
let truncate2 elt list = (* let's not mind how List.find does it version *)
let r = ref [] in
ignore (List.find (fun x -> r := x :: !r; x = elt) list);
List.rev !r
(* this is more what you're looking for? version *)
type 'a mutcons = { mutable head : 'a; mutable tail : 'a mutlist }
and 'a mutlist = Nil | Cons of 'a mutcons
let rec mutlist_iter f = function
| Nil -> ()
| Cons k -> f k; mutlist_iter f k.tail
let rec truncate3 elt mlist =
mutlist_iter (fun k -> if k.head = elt then k.tail <- Nil) mlist
最后遍历可变列表并将当前单元格变为列表的最后一个(如果它包含给定元素)。
答案 2 :(得分:0)
你所描述的是一种破坏性的数据结构,所以你可以用可变的值和一段时间来完成它。
队列界面是好的。弹出值直到找到欲望元素:
Pseudo alorithm
Do
Current = queue.pop myqueue
Until (current = desiredvalue) or (queue.isempty myqueue)
Return myqueue