我正在尝试在OCaml中实现队列结构,现在编写一个测试值是否在队列中的函数。我最初写了一个正确的 - 或者至少我认为这是正确的 - 函数的实现。但是当我测试它时,我会遇到意外的测试失败。也就是说,当队列为空时它会返回false(一件好事)但在其他所有情况下都会返回false,无论队列是否为空,以及队列是否包含该值。所以我以这种愚蠢的方式(Some h -> true
)重新编写了这个函数,以便试图找出问题所在。即使使用这个哑函数,当我将任何队列和任何值传递给它时,它仍然返回false,所以显然它正在以None
的形式读取每个队列的头部,无论它是否为None
。
包含:
let contains (v: 'a) (q: 'a queue) : bool =
if not (valid q) then failwith "contains: given invalid queue";
let rec loop (value: 'a) (qn: 'a qnode option) : bool =
begin match qn with
| None -> false
| Some h -> true
end
in loop elt q.head
测试
let test () : bool =
let q = create () in
not (contains 1 q)
;; run_test "contains empty" test
let test () : bool =
let q = from_list [2; 3] in
contains 3 q
;; run_test "contains non-empty true" test
let test () : bool =
let q = from_list [2; 3] in
not (contains 4 q)
;; run_test "contains non-empty false" test
此处编写的其他功能已经过测试,并按预期推出。队列类型的类型声明是
type 'a qnode = { v: 'a;
mutable next: 'a qnode option }
type 'a queue = { mutable head: 'a qnode option;
mutable tail: 'a qnode option }
对于每个q.head
为None
的原因,我们将不胜感激。
from_list
一个辅助函数,遍历列表,将每个值转换为qnode并将其链接到下一个,返回结果列表。
let rec vals_to_qnodes (l: 'a list) : 'a qnode list =
begin match l with
| [] -> []
| [h] -> [{v = h; next = None}]
| h1::h2::t -> let sofar = vals_to_qnodes (h2::t) in
begin match sofar with
| [] -> []
| x::y -> {v = h1; next = Some x}::x::y
end
end
制作qnodes列表,找到它的第一个和最后一个元素,并将它们指定为队列的头部和尾部。
let from_list (l: 'a list) : 'a queue =
let qsList = vals_to_qnodes l in
begin match qsList with
| [] -> create ()
| h::t -> begin match t with
| [] -> {head = Some h; tail = Some h}
| h2::t2 -> let x = List.rev t2 in
begin match x with
| [] -> {head = None; tail = None;}
| h3::t3 -> {head = Some h; tail = Some h3}
end
end
end
在我尝试简化它以缩小奇怪的行为之前,这是我最初用于包含函数的内容。
let contains (v: 'a) (q: 'a queue) : bool =
if not (valid q) then failwith "contains: given invalid queue";
let rec loop (value: 'a) (qn: 'a qnode option) : bool =
begin match qn with
| None -> false
| Some h -> if v == value then true
else loop value h.next
end
in loop v q.head
答案 0 :(得分:2)
当我尝试您的代码时,它的行为与您描述的不同:
# let n = { v = 1; next = None };;
val n : int qnode = {v = 1; next = None}
# let q = { head = Some n; tail = Some n };;
val q : int queue =
{head = Some {v = 1; next = None}; tail = Some {v = 1; next = None}}
# contains 3 q;;
- : bool = true
所以,我会说答案取决于from_list
实际返回的内容。
作为附加评论,您对contains
的定义引用了elt
,我在任何可以看到的地方都没有定义。
<强>更新强>
您的新代码未定义create
。我为create
提供了这个定义:
let create () = { head = None; tail = None }
如果我运行from_list [1;2]
,这就是我所看到的:
# from_list [1;2];;
- : int queue = {head = None; tail = None}
这可以解释为什么头部看起来是None
: - )