最近由于项目需要,需要用OCaml语言去实现一个循环队列去实现一些功能。翻遍了Ocaml的官方网站和标准库,发现OCaml只提供普通的队列,于是自己基于Array模块设计了循环队列RoundRobinQueue的模块。
主要类型由array队列,对头队尾指针front和rear组成。
mli文件如下:
type 'a round_robin_queue2 = { queue : 'a array ; mutable front : int ; mutable rear : int };;
val create : int -> 'a -> 'a round_robin_queue2
val iter : ('a -> 'b) -> 'a round_robin_queue2 -> unit
val length : 'a round_robin_queue2 -> int
val get : 'a round_robin_queue2 -> int -> 'a option
val peek : 'a round_robin_queue2 -> 'a option
val clear : 'a round_robin_queulengthe2 -> unit
val copy : 'a round_robin_queue2 -> 'a round_robin_queue2
val enqueue : 'a round_robin_queue2 -> 'a -> unit
val transfer : 'a round_robin_queue2 -> 'a round_robin_queue2 -> unit
val dequeue : 'a round_robin_queue2 -> 'a option
val pfarray : ('a -> 'b) -> 'a round_robin_queue2 -> unit
突然发现csdn的markdown编辑器,竟然不识别ocaml语言,不能高亮显示。心态有点小崩……
具体函数实现代码我放在了我的资源当中,有需求的同学请自取。
模块测试代码如下:
open RoundRobinQueue
type data = { size : int ; time : float };;
type packet = { src : int ; port : int };;
let data1 ={ size =64 ; time =456.};;
let data2 ={ size =128 ; time =1234.};;
let packet1 ={ src =177667 ; port =6};;
let packet2 ={ src =166666 ; port =2};;
let pfdata a = print_string ("s:"^(string_of_int a.size)^ "t:"^(string_of_float a.time));;
let pfpacket a = print_string ("src:"^(string_of_int a.src)^ "port:"^(string_of_int a.port));;
let pfqueuedata f a =
let elem = RoundRobinQueue.get a 8 in
print_int (a.front);
print_int (a.rear);
print_string("-");
print_int (length a);
print_string("-");
iter f a;
match elem with
None -> print_string("None");
| Some data -> print_string ("Some "); f data;
print_newline();
;;
let loop f sum =
let rec loop1 f n =
if n >= 0 then begin f(); loop1 f (n -1) end else () in
loop1 f sum;;
let _ =
let a = create 10 data1 in
let loopq l d s = begin enqueue l d;
pfqueuedata pfdata l ;
print_newline(); end in
let loopq1 l s = begin dequeue l ;
pfqueuedata pfdata l ;
print_newline(); end in
(* pfqueuedata a; print_newline(); enqueue a data2; pfqueuedata a ; *)
(* print_newline(); dequeue a; pfqueuedata a ; print_int (10 mod 8) *)
loop (loopq a data2 ) 10;
loop (loopq1 a) 10;
let b = copy a in
transfer a b;
loop (loopq1 b) 10;
loop (loopq b data2) 10;
;;
let _ =
let a = create 10 packet1 in
let loopq l d s = begin enqueue l d;
pfqueuedata pfpacket l ;
print_newline(); end in
let loopq1 l s = begin dequeue l ;
pfqueuedata pfpacket l ;
print_newline(); end in
(* pfqueuedata a; print_newline(); enqueue a data2; pfqueuedata a ; *)
(* print_newline(); dequeue a; pfqueuedata a ; print_int (10 mod 8) *)
loop (loopq a packet2 ) 10;
loop (loopq1 a) 10;
let b = copy a in
transfer a b;
loop (loopq1 b) 10;
loop (loopq b packet2) 10;
;;
测试结果如下:
01-1-s:128t:1234.None
02-2-s:128t:1234.s:128t:1234.None
03-3-s:128t:1234.s:128t:1234.s:128t:1234.None
04-4-s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.None
05-5-s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.None
06-6-s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.None
07-7-s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.None
08-8-s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.None
09-9-s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.Some s:128t:1234.
10-9-s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.Some s:128t:1234.
21-9-s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.Some s:128t:1234.
31-8-s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.None
41-7-s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.None
51-6-s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.None
61-5-s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.None
71-4-s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.None
81-3-s:128t:1234.s:128t:1234.s:128t:1234.None
91-2-s:128t:1234.s:128t:1234.None
01-1-s:128t:1234.None
11-0-None
11-0-None
11-0-None
11-0-None
11-0-None
11-0-None
11-0-None
11-0-None
11-0-None
11-0-None
11-0-None
11-0-None
11-0-None
11-0-None
12-1-s:128t:1234.None
13-2-s:128t:1234.s:128t:1234.None
14-3-s:128t:1234.s:128t:1234.s:128t:1234.None
15-4-s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.None
16-5-s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.None
17-6-s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.None
18-7-s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.None
19-8-s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.None
10-9-s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.Some s:128t:1234.
21-9-s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.Some s:128t:1234.
32-9-s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.s:128t:1234.Some s:128t:1234.
01-1-src:166666port:2None
02-2-src:166666port:2src:166666port:2None
03-3-src:166666port:2src:166666port:2src:166666port:2None
04-4-src:166666port:2src:166666port:2src:166666port:2src:166666port:2None
05-5-src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2None
06-6-src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2None
07-7-src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2None
08-8-src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2None
09-9-src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2Some src:166666port:2
10-9-src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2Some src:166666port:2
21-9-src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2Some src:166666port:2
31-8-src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2None
41-7-src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2None
51-6-src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2None
61-5-src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2None
71-4-src:166666port:2src:166666port:2src:166666port:2src:166666port:2None
81-3-src:166666port:2src:166666port:2src:166666port:2None
91-2-src:166666port:2src:166666port:2None
01-1-src:166666port:2None
11-0-None
11-0-None
11-0-None
11-0-None
11-0-None
11-0-None
11-0-None
11-0-None
11-0-None
11-0-None
11-0-None
11-0-None
11-0-None
11-0-None
12-1-src:166666port:2None
13-2-src:166666port:2src:166666port:2None
14-3-src:166666port:2src:166666port:2src:166666port:2None
15-4-src:166666port:2src:166666port:2src:166666port:2src:166666port:2None
16-5-src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2None
17-6-src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2None
18-7-src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2None
19-8-src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2None
10-9-src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2Some src:166666port:2
21-9-src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2Some src:166666port:2
32-9-src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2src:166666port:2Some src:166666port:2
经过测试,模块能够实现原本标准库里Queue模块的大多数功能,满足基本的使用。
在设计模块的过程中,需要注意以下几点:
- 设计一个mli时,要选择是提供类型的具体定义还是保持为抽象类型,大多数情况下正确地选择都是保持为抽象类型,这样可以提高设计的灵活性,模块使用可以确保不变式约束。
抽象可以提高灵活性,通过限制用于与类型的交互,从而尽可能减少用户对实现细节的依赖。 - 在写模块接口时,不只是要考虑那些读mli文件的人能够很容易地理解的接口,更重要的,对于那些读调用点代码的人,要让调用尽可能清晰。