Ocaml和返回类型(图论)
我只是Ocaml中的乞丐,我想学习图论,但要用Ocaml实现。我在做一些事情时遇到了麻烦:我只想通过深度优先搜索列出一个图中连接的组件。所以,我做到了:Ocaml和返回类型(图论),ocaml,graph-theory,return-type,Ocaml,Graph Theory,Return Type,我只是Ocaml中的乞丐,我想学习图论,但要用Ocaml实现。我在做一些事情时遇到了麻烦:我只想通过深度优先搜索列出一个图中连接的组件。所以,我做到了: #open "stack" ;; let non_empty pile = try push (pop pile) pile ; true with Empty -> false ;; let connected_comp g = let already_seen = make_vect (vect_length
#open "stack" ;;
let non_empty pile =
try push (pop pile) pile ; true with Empty -> false ;;
let connected_comp g =
let already_seen = make_vect (vect_length g) false in
let comp = [] in
let dfs s lst =
let totreat = new () in
already_seen.(s) <- true; push s totreat;
let rec add_neighbour l = match l with
| [] -> ()
| q::r when already_seen.(q) = false -> push q totreat; already_seen.(q) <- true; add_neighbour r
| q::r -> add_neighbour r
in
while non_empty totreat do
let s = pop totreat in
already_seen.(s) <- true;
(* we want to add s to the list lst *) s::lst;
add_neighbour g.(s);
done
in
let rec head_list l = match l with
| [] -> failwith "Empty list"
| p::q -> p
in
let rec aux comp t = match t with
| t when t = vect_length g -> comp
| t when already_seen.(t) = true -> aux comp (t+1)
| t -> aux ((dfs t [])::comp) (t+1) (* we want that dfs t [] return the list lst modified *)
in aux comp 0;;
(alreadyseen是一个布尔向量,前面已定义)
我唯一的问题是,我希望函数返回listlst
modified(在循环中),此时,它是一个单位函数
我试图将lst定义为引用,但我不知道如何返回它
我希望这更清楚,我现在还不熟悉这一切
谢谢大家! 这是您的代码的降级版本,演示了一种实现所需功能的方法
let non_empty _ = false
let dfs s lst =
let local_lst = ref lst in
while non_empty () do
(*do stuff here*)
let s = 1 in
local_lst := s::!local_lst;
(*do stuff here*)
done;
!local_lst
我首先将一个局部可变值
local_lst
初始化为作为参数给出的列表lst
。然后在while
循环中更新该值。最后,我返回存储在local_lst
中的值,尝试编写代码的最低版本,该版本只包含dfs
的定义,不依赖外部数据类型。这将使我们更容易帮助你。另外请注意,如果您想“了解OCaml”,学习编写递归函数和避免副作用是重点。请注意,代码示例是在Caml灯光下,而不是在OCaml中。它非常完美,非常感谢!是否也可以要求函数dfs的lst参数作为参考,直接修改它并在最后返回它?无论如何,非常感谢!是lst
可以是引用,如果这样做,则不需要在末尾返回它,因为引用将被修改。然后,函数的返回类型将是unit
,您可以重用您提供的引用作为参数。非常感谢您的所有解释!)但是使用引用并不是ocaml的方式。通常在函数式语言中,您会返回新值,而不是修改任何内容。@GoswinvonBrederlow是正确的。你应该学会不使用可变值,你会很快看到好处,因为调试变得容易多了。
let dfs s lst =
let totreat = new () in
already_seen.(s) <- true; push s totreat;
let rec add_neighbour l = match l with
| [] -> ()
| q::r when already_seen.(q) = false -> push q totreat; already_seen.(q) <- true; add_neighbour r
| q::r -> add_neighbour r
in
while non_empty totreat do
let s = pop totreat in
already_seen.(s) <- true;
(* we want to add s to the list lst *) s::lst;
add_neighbour g.(s);
done
in
let non_empty _ = false
let dfs s lst =
let local_lst = ref lst in
while non_empty () do
(*do stuff here*)
let s = 1 in
local_lst := s::!local_lst;
(*do stuff here*)
done;
!local_lst