Có một cách: functors lẫn nhau đệ quy. Xem this bài viết tuyệt vời về biên soạn riêng trong OCaml và this bài viết đầy cảm hứng cung cấp ý tưởng chính.
Đây là một ví dụ. Tôi đã tạo giao diện 4 MLI-files:
$ ls *.mli
Make_moduleA.mli Make_moduleB.mli ModuleA.mli ModuleB.mli
và 3 thực hiện tập tin:
$ ls *.ml
Make_moduleA.ml Make_moduleB.ml main.ml
Dưới đây là nội dung các tập tin giao diện:
(* ModuleA.mli *)
module type ModuleA = sig
val fa : int -> unit
end
(* ModuleB.mli *)
module type ModuleB = sig
val fb : int -> unit
end
(* Make_moduleA.mli *)
open ModuleA
open ModuleB
module type Make_moduleA_sig =
functor (Mb : ModuleB) ->
sig
val fa : int -> unit
end
module Make_moduleA : Make_moduleA_sig
(* Make_moduleB.mli *)
open ModuleA
open ModuleB
module type Make_moduleB_sig =
functor (Ma : ModuleA) ->
sig
val fb : int -> unit
end
module Make_moduleB : Make_moduleB_sig
Và đôi bên cùng có functors đệ quy:
(* Make_moduleA.ml *)
open ModuleA
open ModuleB
module type Make_moduleA_sig =
functor (Mb : ModuleB) ->
sig
val fa : int -> unit
end
module Make_moduleA_impl =
functor (Mb : ModuleB) ->
struct
let rec fa (n : int) =
if n > 0 then
(Printf.printf "A: %d\n" n;
Mb.fb (n - 1))
end
module Make_moduleA = (Make_moduleA_impl : Make_moduleA_sig)
(* Make_moduleB.ml *)
open ModuleA
open ModuleB
module type Make_moduleB_sig =
functor (Ma : ModuleA) ->
sig
val fb : int -> unit
end
module Make_moduleB_impl =
functor (Ma : ModuleA) ->
struct
let rec fb (n : int) =
if n > 0 then
(Printf.printf "B: %d\n" n;
Ma.fa (n - 1))
end
module Make_moduleB = (Make_moduleB_impl : Make_moduleB_sig)
Và bây giờ chúng ta hãy kết hợp các module:
(* main.ml *)
open ModuleA
open ModuleB
open Make_moduleA
open Make_moduleB
module rec MAimpl : ModuleA = Make_moduleA(MBimpl)
and MBimpl : ModuleB = Make_moduleB(MAimpl)
let _ = (* just a small test *)
MAimpl.fa 4;
print_endline "--------------";
MBimpl.fb 4
Build lệnh trình tự:
ocamlc -c ModuleA.mli
ocamlc -c ModuleB.mli
ocamlc -c Make_moduleA.mli
ocamlc -c Make_moduleB.mli
ocamlc -c Make_moduleA.ml
ocamlc -c Make_moduleB.ml
ocamlc -c main.ml
ocamlc Make_moduleA.cmo Make_moduleB.cmo main.cmo
Kết quả thử nghiệm:
$ build.sh && ./a.out
A: 4
B: 3
A: 2
B: 1
--------------
B: 4
A: 3
B: 2
A: 1
Nguồn
2016-04-21 20:12:49
Bạn có thể làm sáng tỏ một chút về bối cảnh của vấn đề này không? Tôi chỉ tò mò: nếu đó là một số loại mã được tạo tự động, thì tại sao lại bận tâm? –
Nó không phải là mã được tạo tự động, tôi đã tự viết các chức năng này ... – SoftTimur
Tệp đó dài bao lâu? Nếu nó được viết bằng tay, tôi sẽ không chia nó (vì bạn có thể mất cả hiệu quả và khả năng đọc). –