To: caml-list@inria.fr
Subject: strange behavior of the object type-checker
From: Pierre Boulet <Pierre.Boulet@lifl.fr>
Date: 09 Sep 1999 18:34:19 +0200
dear ocamllers,
I have finally decided to give a try to the object subsystem of ocaml
and I have stumbled on something very strange (for me, at least).
In the code I present below, after some parametric class creation, I
try to execute some method of an object. Three *successive* tries give
three *different* results: two different typing error messages and
finally success.
This code has been tested with ocaml 2.02 and the cvs version of
yesterday (8 sept.), ocaml 2.02+3. They give the same result.
My aim is to define a graph class which implements simple graph
algorithms such as depth first scanning. Anyway, here is the code.
class ['e] node g n0 =
object (self)
val mutable mark = true (* a boolean to handle cycles *)
method mark = mark
method set_mark = mark <- true
method unset_mark = mark <- false
val mutable edges = ([] : 'e list) (* outgoing edges *)
method edges = edges
method add_edge e = edges <- e::edges
initializer g#add_node self (* registration into the graph *)
val n = n0 (* dummy printing *)
method n = n
method draw =
Printf.printf "node: %i\n" n
method iter fn fe = (* depth first iteration *)
if self#mark then
begin
fn self;
self#unset_mark;
List.iter (fun e -> e#iter fn fe) edges
end
end;;
class ['n] edge g from_init towards_init =
object (self)
val mutable mark = true (* a boolean to handle cycles *)
method mark = mark
method set_mark = mark <- true
method unset_mark = mark <- false
val from = (from_init : 'n)
val towards = (towards_init : 'n)
method from = from
method towards = towards
initializer g#add_edge self (* registration into the graph *)
initializer from#add_edge self (* registration into the from node *)
method draw = (* dummy printing *)
Printf.printf "edge: %i->%i\n" from#n towards#n
method iter fn fe = (* depth first iteration *)
if self#mark then
begin
fe self;
self#unset_mark;
towards#iter fn fe
end
end;;
class ['n,'e] graph =
object (self)
val mutable nodes = ([] : 'n list) (* list of nodes *)
method nodes = nodes
val mutable start_node = (None : 'n option)
method start_node = start_node
method set_start_node n = start_node <- Some n
method add_node n =
nodes <- n::nodes;
match nodes with
| [n] -> self#set_start_node n
| _ -> ()
val mutable edges = ([] : 'e list) (* list of edges *)
method edges = edges
method add_edge e = edges <- e::edges
method set_marks =
List.iter (fun n -> n#set_mark) nodes;
List.iter (fun e -> e#set_mark) edges
method iter (fn : 'n -> unit) (fe : 'e -> unit) = (* depth first iteration *)
match start_node with
| None -> failwith "set start node first"
| Some n ->
self#set_marks;
(n#iter fn fe : unit)
end;;
let g = new graph;;
g#iter (fun n -> n#draw) (fun e -> e#draw);;
let n1 = new node g 1;;
g#iter (fun n -> n#draw) (fun e -> e#draw);;
(* until now, everything goes fine *)
let e11 = new edge g n1 n1;;
g#iter (fun n -> n#draw) (fun e -> e#draw);;
(* returns:
Characters 17-18:
This expression has type 'a edge node as 'a
It has no method draw
*)
g#iter (fun n -> n#draw) (fun e -> e#draw);;
(* returns:
Characters 0-1:
This expression has type
(('a edge as 'b) node as 'a, ('c node as 'd) edge as 'c) graph
It has no method iter
*)
g#iter (fun n -> n#draw) (fun e -> e#draw);;
(* returns as expected:
node: 1
edge: 1->1
- : unit = ()
*)
So what happens? It seems that adding an edge to the graph unsettles
the type checker...
any thought?
-- Pierre.
This archive was generated by hypermail 2b29 : Sun Jan 02 2000 - 11:58:25 MET