【发布时间】:2017-10-11 02:23:20
【问题描述】:
我正在尝试在 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
在我尝试简化它以缩小奇怪行为之前,这是我最初对 contains 函数所做的。
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
【问题讨论】: