From mboxrd@z Thu Jan 1 00:00:00 1970 Received: (from weis@localhost) by pauillac.inria.fr (8.6.10/8.6.6) id RAA24584 for caml-redistribution; Thu, 12 Sep 1996 17:06:34 +0200 Received: from concorde.inria.fr (concorde.inria.fr [192.93.2.39]) by pauillac.inria.fr (8.6.10/8.6.6) with ESMTP id OAA21270 for ; Thu, 12 Sep 1996 14:14:19 +0200 Received: from news2.tokyo.intervia.ad.jp (news2.tokyo.intervia.ad.jp [202.235.64.84]) by concorde.inria.fr (8.7.1/8.7.1) with SMTP id OAA23304 for ; Thu, 12 Sep 1996 14:14:15 +0200 (MET DST) Received: from sparc1.nextsolution.co.jp (sparc1.nextsolution.co.jp [202.235.80.1]) by news2.tokyo.intervia.ad.jp (8.6.12+2.4W/intervia-1.7u) with SMTP id VAA21431 for ; Thu, 12 Sep 1996 21:14:09 +0900 Received: from sparc3.nextsolution.co.jp by sparc1.nextsolution.co.jp (5.x/SMI-SVR4) id AA09839; Thu, 12 Sep 1996 21:12:50 +0900 Received: by sparc3.nextsolution.co.jp (5.x/SMI-SVR4) id AA00935; Thu, 12 Sep 1996 21:13:01 +0900 Date: Thu, 12 Sep 1996 21:13:01 +0900 From: christo@nextsolution.co.jp (Frank Christoph) Message-Id: <9609121213.AA00935@sparc3.nextsolution.co.jp> To: caml-list@pauillac.inria.fr In-Reply-To: <9609120953.AA00876@sparc3.nextsolution.co.jp> (christo@nextsolution.co.jp) Subject: Re: As-binding #-types/Evaluation order & State Sender: weis In the last message, I wrote: > The manual says you can use "as" to bind row variables in a type, so > "#myclass as 'a -> 'a" would be the type of a function to and from equal > types, instead of possibly different descendants of "#myclass". > But I've had trouble using this type expression in type definitions. > #type 'a mytype = Mk of #myclass;; > Unbound row variable in #myclass > is an error as expected, but > #type 'a mytype = Mk of #myclass as 'a;; > Unbound row variable in #myclass > yields the same problem. Shouldn't this be possible? but I think I misunderstood the difference between "#myclass" and simply "myclass". I wasn't expecting to be able to use the methods of an arbitrary descendant of myclass after pattern matching mytype, I just wanted to constrain the polymorphic variable 'a -- so I suppose the correct declaration would be #type 'a mytype = Mk of myclass;; and use coercion on descendants I want to instantiate it with. In fact, I have a completely different question, though, and I expect most people will probably be familiar with it. Quite often I have come across problems because of the interaction of evaluation order and state updates. The most recent example I encountered was with writing a function that converts a Queue.t to a list. #let rec list_of_queue q = # try Queue.take q :: list_of_queue q with Queue.Empty -> [] Clearly this function will not terminate because the right argument of "::" gets evaluated first. So either we need to sequence the evaluation of the two sides or pass a different argument to the recursive call of list_of_queue. But if we use ";", then the result of the first computation is discarded, so the only way I see to do it explicitly is something like, #let rec list_of_queue q = # let e = ref None in # try e := Some (Queue.take q); # (match !e with Some x -> x) :: list_of_queue q # with Queue.Empty -> [] where the option type is necessary since there is no other reasonable initialization value for the reference. Of course, there is a much simpler way, #let rec list_of_queue q = # let cons tl hd = hd :: tl in # try cons (list_of_queue q) (Queue.take q) # with Queue.Empty -> [] but this also seems pretty contrived. Furthermore, in those cases where we CAN implicitly rely on the evaluation order to do the updates in the proper order, we're setting ourselves up for disaster if the function gets modified later on by some unsuspecting soul. So, how do most people usually handle this problem? Is there a straightforward, safe, efficient solution? ------------------------------------------------------------------------ Frank Christoph Next Solution Co. Tel: 0424-98-1811 christo@nextsolution.co.jp Fax: 0424-98-1500