caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* strange behavior of the object type-checker
@ 1999-09-09 16:34 Pierre Boulet
  1999-09-09 19:43 ` Jerome Vouillon
  0 siblings, 1 reply; 12+ messages in thread
From: Pierre Boulet @ 1999-09-09 16:34 UTC (permalink / raw)
  To: caml-list

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.




^ permalink raw reply	[flat|nested] 12+ messages in thread
* Re: Can someone explain?
@ 1999-10-13 19:16 Juergen Pfitzenmaier
  0 siblings, 0 replies; 12+ messages in thread
From: Juergen Pfitzenmaier @ 1999-10-13 19:16 UTC (permalink / raw)
  To: caml-list

Lyn A Headley wrote:
> An ocaml "port" of STL would kick ass.  especially, think how well
> iterators would combine with closures!  The C++ notion of "function
> objects" and "adaptors" looks clumsy in comparison (e.g. you cannot
> create a localized class object)

Hmm, don't know if it would be the same nice thing as in C++. A year ago
I added a GC to the STL containers so there's some experience of what
can happen if you try this in ocaml.
Some algorithms using the STL are built around the fact that certain iterators
and the value they refer to don't change if you treat the container ``nicely''.
To keep these algos working was quite some pain.
Haven't really thought about what happens if the GC is a real member of the
language and not just an add-on. May be things are easier then but I wouldn't
bet on it.
ciao pfitzen




^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~1999-10-14 13:01 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-09-09 16:34 strange behavior of the object type-checker Pierre Boulet
1999-09-09 19:43 ` Jerome Vouillon
1999-09-28 18:56   ` Can someone explain? skaller
1999-10-04  8:23     ` Pierre Weis
1999-10-04 22:57       ` skaller
1999-10-05  9:43         ` Jerome Vouillon
1999-10-05 19:35         ` Gerd Stolpmann
1999-10-06  9:42           ` skaller
1999-10-08  0:17           ` Problem of coercion in recursive class definitions Peter Schrammel
1999-10-05 21:42         ` Can someone explain? Lyn A Headley
1999-10-06 10:17           ` skaller
1999-10-13 19:16 Juergen Pfitzenmaier

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).