From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.1.3 (2006-06-01) on yquem.inria.fr X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=disabled version=3.1.3 X-Original-To: caml-list@yquem.inria.fr Delivered-To: caml-list@yquem.inria.fr Received: from mail2-relais-roc.national.inria.fr (mail2-relais-roc.national.inria.fr [192.134.164.83]) by yquem.inria.fr (Postfix) with ESMTP id 02019BBCA for ; Tue, 26 Feb 2008 15:24:35 +0100 (CET) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: Ao8CAAuww0fBXxGuaWdsb2JhbACBVY8BDQsEBBMRBIEQmwQ X-IronPort-AV: E=Sophos;i="4.25,407,1199660400"; d="scan'208";a="7722671" Received: from gw4.outgw.tn (HELO rissala174.outgw.tn) ([193.95.17.174]) by mail2-smtp-roc.national.inria.fr with ESMTP; 26 Feb 2008 15:24:34 +0100 Received: from smtp.hexabyte.tn (smtp.hexabyte.tn [213.150.189.11]) by tounes-20.ati.tn (Postfix) with ESMTP id 58300F3803F for ; Tue, 26 Feb 2008 15:24:32 +0100 (CET) Received: from Netconsult ([41.227.249.105]) by smtp.hexabyte.tn with SMTPœ id m1QEOVLH021464 Message-ID: <004d01c87883$4d5f76d0$01fea8c0@Netconsult> From: "Netconsult International" To: References: <20080226140500.2094FBC70@yquem.inria.fr> Subject: Re: Caml-list Digest, Vol 32, Issue 71 Date: Tue, 26 Feb 2008 15:24:30 +0100 MIME-Version: 1.0 Content-Type: text/plain; format=flowed; charset="iso-8859-1"; reply-type=original Content-Transfer-Encoding: 8bit X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 6.00.2900.3138 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.3198 X-Antivirus: avast! (VPS 080225-0, 25/02/2008), Outbound message X-Antivirus-Status: Clean X-Spam: no; 0.00; berke:01 durak:01 berke:01 durak:01 functors:01 ocaml's:01 runtime:01 pointer:01 scalable:01 parametrize:01 printf:01 printf:01 buffer:01 buffer:01 val:01 please remove my adress from you list Best regards ----- Original Message ----- From: To: Sent: Tuesday, February 26, 2008 3:05 PM Subject: Caml-list Digest, Vol 32, Issue 71 > Send Caml-list mailing list submissions to > caml-list@yquem.inria.fr > > To subscribe or unsubscribe via the World Wide Web, visit > http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list > or, via email, send a message with subject or body 'help' to > caml-list-request@yquem.inria.fr > > You can reach the person managing the list at > caml-list-owner@yquem.inria.fr > > When replying, please edit your Subject line so it is more specific > than "Re: Contents of Caml-list digest..." > > > Today's Topics: > > 1. Objects, dynamic cast, Obj.magic abuse and dragons (Berke Durak) > 2. Re: Objects, dynamic cast, Obj.magic abuse and dragons > (Richard Jones) > 3. Unexpected restriction in "let rec" expressions (Loup Vaillant) > 4. Re: Objects, dynamic cast, Obj.magic abuse and dragons (ketti) > 5. Re: Objects, dynamic cast, Obj.magic abuse and dragons > (Berke Durak) > 6. Re: Unexpected restriction in "let rec" expressions > (Jean-Christophe Filli?tre) > > > ---------------------------------------------------------------------- > > Message: 1 > Date: Tue, 26 Feb 2008 12:35:10 +0100 > From: Berke Durak > Subject: [Caml-list] Objects, dynamic cast, Obj.magic abuse and > dragons > To: Caml-list List > Message-ID: <47C3F96E.4080901@exalead.com> > Content-Type: text/plain; charset="utf-8" > > Hello, > > It seems that objects are back in fashion again on the list. > > As records of functions or functors dont quite cut the mustard for some > applications, I decided to give Ocaml's object > system another try. I tried to implement a conventional text adventure > using those, of the "go north take sword kill > dragon" kind. Actually I had one such small prototype I wrote while > learning Java, so I decided to port that one. > > I've stumbled on a situation where I feel dynamic casting could be useful. > At least, that is the way I did it in the > Java version. I've worked around it using Obj.magic, but I can't check > the class, so this could lead to nastiness. > I'd rather eat a runtime Class_cast_exception than a segmentation fault. > > In this adventure, things can contain other things; a class physical has a > list of things it contains, and an optional > pointer to its container. > > Persons, places and objects are things so they inherit from physical. > Hence, a forest is a place that can contain > a sword (an object), a dragon (a person) or another place (a small house). > Persons can be contained in places > or things (coffins). > > The problem is that the main game loop gets the current location by taking > the container of the hero... which is a > physical. However, it needs to call the place-specific method "go". > > I'm submitting my example so that you can propose alternative solutions. > A few ideas: > > * Add a go method in physical, raise an exception - not scalable, if I > want to add other categories of things, > I'll have to add the corresponding method to physical. > * Parametrize physical with the type of contents. > * Use a sum type; but then it wouldn't be an object any more, and it's a > centralized place. > -- > Berke DURAK > -------------- next part -------------- > (* Adventure *) > > exception QuitException > > let mandatory = function > | None -> raise Not_found > | Some x -> x > > let pf = Printf.printf > > let split_at c u = > let m = String.length u in > let b = Buffer.create m in > let rec loop0 r i = > if i >= m then > List.rev r > else > if u.[i] = c then > loop0 r (i + 1) > else > loop1 r i > and loop1 r i = > if i = m or u.[i] = c then > begin > let x = Buffer.contents b in > Buffer.clear b; > loop0 (x::r) (i + 1) > end > else > begin > Buffer.add_char b u.[i]; > loop1 r (i + 1) > end > in > loop0 [] 0 > > let ( & ) f x = f x > > class ['subject] io in_channel () = > object > val mutable subject : 'subject option = None > method set_subject s = subject <- Some s > method get_subject = mandatory subject > > method read = > pf "< %!"; > split_at ' ' & input_line in_channel > > method write u = > pf ">>> %s\n%!" u > end > > class virtual command = > object > method virtual get_verb : string > method virtual perform : string list -> unit > end > > class virtual describable = > object > method virtual describe : 'a . 'a io -> unit > method virtual get_name : string > end > > class virtual physical = > object(self) > inherit describable as super > val mass = 1.0 > val takeable = true > val mutable contents : physical list = [] > val mutable container : physical option = None > method contents = contents > method container = mandatory container > > method add : physical -> unit = fun thing -> contents <- thing :: > contents > > method remove (thing : physical) = contents <- List.filter ((<>) thing) > contents > > method unlink = > match container with > | None -> () > | Some t -> t#remove (self :> physical) > > method put (target : physical) = > self#unlink; > container <- Some target; > target#add (self :> physical) > > end > > class biscuit = > object > inherit physical as super > method describe io = > io#write "A square biscuit with chocolate in it. It is organic, or > at least that's what the writing on it, presumably in edible, organic ink, > says."; > method get_name = "a chocolate biscuit" > method to_string = "the biscuit" > end > > type direction = N | S | E | W > > let invert = function > | N -> S > | S -> N > | E -> W > | W -> E > > let connect p1 d p2 = > p1#connect d p2; > p2#connect (invert d) p1 > > class virtual place = > object(self) > inherit physical as super > val mutable seen = false > val mutable outlinks : (direction * place) list = [] > > method go d = List.assoc d outlinks > > method connect d t = outlinks <- (d, t) :: outlinks > > method describe_items : 'a . 'a io -> unit = fun io -> > io#write "You can see:"; > List.iter > (fun p -> > let (q : physical) = p in > q#describe io > ) > contents > > method virtual describe_place : 'a . 'a io -> unit > > method describe io = > self#describe_place io; > self#describe_items io > end > > class virtual person = > object > inherit physical as super > val takeable = false > end > > class hero = > object > inherit person as super > method get_name = "John" > method describe io = io#write "John is a tall man." > end > > let sf = Printf.sprintf > > class forest name () = > object(self) > inherit place as super > method get_name = name > method describe_place io = > io#write (sf "You are in %s" self#get_name) > end > > class sword = > object(self) > inherit physical as super > > method describe io = > io#write "A one-meter long, titanium alloy, gold-plated, > emerald-incrusted, Dragon-repelling adventurer's heavy duty sword." > > method get_name = "A golden sword" > end > > class game io = > let f1 = new forest "the big dark forest" () in > let f2 = new forest "the small dark forest" () in > let f3 = new forest "the small light forest" () in > let f4 = new forest "the tropical forest" () in > let h = new hero in > let _ = h#put (f1 :> physical) in > let _ = connect f1 N f2 in > let _ = connect f2 E f3 in > let _ = connect f3 S f4 in > let _ = connect f4 E f1 in > let _ = io#set_subject h in > let sw = new sword in > let _ = sw#put (f1 :> physical) in > let b = new biscuit in > let _ = b#put (f4 :> physical) in > object(self) > method where = > let wh' = h#container in > (* XXXXXXXX here *) > let wh : place = Obj.magic wh' in (* I'd like a dynamic cast here! *) > (* XXXXXXXX *) > (*let wh' = (h#container : physical <: place) in*) > wh > > method go d = > try > let wh = self#where in > let wh = wh#go d in > h#put (wh : place :> physical) > with > | Not_found -> > io#write "Can't go there" > > method run = > let wh = self#where in > wh#describe io; > begin > match io#read with > | ["n"] -> self#go N > | ["s"] -> self#go S > | ["e"] -> self#go E > | ["w"] -> self#go W > | _ -> io#write "Wtf?" > end > end > > let play () = > let io = new io stdin () in > let g = new game io in > while true do > g#run > done > > ------------------------------ > > Message: 2 > Date: Tue, 26 Feb 2008 12:14:51 +0000 > From: Richard Jones > Subject: Re: [Caml-list] Objects, dynamic cast, Obj.magic abuse and > dragons > To: Berke Durak > Cc: Caml-list List > Message-ID: <20080226121451.GA20860@annexia.org> > Content-Type: text/plain; charset=us-ascii > > On Tue, Feb 26, 2008 at 12:35:10PM +0100, Berke Durak wrote: >> The problem is that the main game loop gets the current location by >> taking >> the container of the hero... which is a physical. However, it needs to >> call the place-specific method "go". > > I only briefly read over this, but maybe the thing you want is an > object memo. There's a specialized one in lablgtk called GUtil.memo, > but the basic source for it could be adapted: > > class ['a] memo () = object > constraint 'a = #widget > val tbl = Hashtbl.create 7 > method add (obj : 'a) = > Hashtbl.add tbl obj#get_id obj > method find (obj : widget) = Hashtbl.find tbl obj#get_id > method remove (obj : widget) = Hashtbl.remove tbl obj#get_id > end > > There's an example of using this if you search down for 'memo' on this > page: > > http://www.ocaml-tutorial.org/introduction_to_gtk > > Rich. > > -- > Richard Jones > Red Hat > > > > ------------------------------ > > Message: 3 > Date: Tue, 26 Feb 2008 13:24:57 +0100 > From: "Loup Vaillant" > Subject: [Caml-list] Unexpected restriction in "let rec" expressions > To: "Caml List" > Message-ID: > <6f9f8f4a0802260424o5bce2fd9i89fbfa38bb239a6a@mail.gmail.com> > Content-Type: text/plain; charset=ISO-8859-1 > > hello, > > I was trying to translate this simple Haskell definition in Ocaml: > > loop :: ((a,c) -> (b,c)) -> a -> b > loop f a = b > where (b,c) = f (a,c) > > However, the direct translation doesn't work: > > # let loop f a = > let rec (b, c) = f (a, c) in > b;; > Characters 25-31: > let rec (b, c) = f (a, c) in > ^^^^^^ > Only variables are allowed as left-hand side of `let rec' > > So I try to bypass this restriction: > > # let loop f a = > let rec couple = f (a, snd couple) in > fst couple;; > Characters 34-51: > let rec couple = f (a, snd couple) in > ^^^^^^^^^^^^^^^^^ > This kind of expression is not allowed as right-hand side of `let rec' > > > Any ideas about what is this restriction, an what is it for? > > Thanks, > Loup > > > > ------------------------------ > > Message: 4 > Date: Tue, 26 Feb 2008 13:48:20 +0100 > From: ketti > Subject: Re: [Caml-list] Objects, dynamic cast, Obj.magic abuse and > dragons > To: "Berke Durak" > Cc: Caml-list List > Message-ID: > <6ebe51ce0802260448i61b968e4tf618edc0580636f5@mail.gmail.com> > Content-Type: text/plain; charset=UTF-8 > > Hi, > > 2008/2/26 Berke Durak : >> Persons, places and objects are things so they inherit from physical. >> Hence, a forest is a place that can contain >> a sword (an object), a dragon (a person) or another place (a small >> house). Persons can be contained in places >> or things (coffins). >> >> The problem is that the main game loop gets the current location by >> taking the container of the hero... which is a >> physical. However, it needs to call the place-specific method "go". > > I too have only read your code briefly, but i would suggest you use > multiple inheritanse. Coffin would inherit from both object and place. > That way the container of the hero is always a place. In fact, that is > the way i would encode it in java too (using interfaces). > > > > ------------------------------ > > Message: 5 > Date: Tue, 26 Feb 2008 14:10:13 +0100 > From: Berke Durak > Subject: Re: [Caml-list] Objects, dynamic cast, Obj.magic abuse and > dragons > Cc: Caml-list List > Message-ID: <47C40FB5.1090603@exalead.com> > Content-Type: text/plain; charset=UTF-8; format=flowed > > I have found a where, for each category C (such as place or person), you > add a method > > as_C : C > > in physical that throws a Class_cast_exception, and override it with a > method that returns > self in class C. However this means that the type C must appear in the > definition of physical, > which means that either > > (a) All categories C1, ..., Cn are defined in the same file in the same > bunch > of mutually-recursive class definitions; a solution evidently not > scalable. > > (b) The physical class is parametrized by n paramters 'C1, 'C2, ... 'Cn, > which > must be repeated everywhere. > > The latter solution works for small n but the complexity of incremental > maintenance is in O(n). > This means that if you define your n classes in n files, you'll have to > edit n files to add > an (n+1)-th class. > > This leads me back to an idea I was talking about with Yann Régis-Gianas > a few months ago : > the ability to bundle type parameters as a named record and to access > their components. > > You could write, in a file > > f.ml: > type ''bundle := ('place, 'person, 'c3, 'c4 ...) > > then in physical.ml : > > class [F.''bundle] physical = > object > method as_place : raise Class_cast_exception > method as_person : raise Class_cast_exception > method as_c3 : raise Class_cast_exception > end > > and in place.ml > class [F.''bundle] place = > object(self : 'a) > constraint ''bundle.'place = 'a > method as_place = self > end > > and so on... I don't know how much sense this makes with respect to > separate compilation. > However, this would allow you to add a category by just editing two files. > -- > Berke DURAK > > > > ------------------------------ > > Message: 6 > Date: Tue, 26 Feb 2008 15:04:44 +0100 > From: Jean-Christophe Filli?tre > Subject: Re: [Caml-list] Unexpected restriction in "let rec" > expressions > To: Loup Vaillant > Cc: Caml List > Message-ID: <47C41C7C.6010006@lri.fr> > Content-Type: text/plain; charset=ISO-8859-1 > > Loup Vaillant a écrit : >> I was trying to translate this simple Haskell definition in Ocaml: >> >> loop :: ((a,c) -> (b,c)) -> a -> b >> loop f a = b >> where (b,c) = f (a,c) >> >> However, the direct translation doesn't work: >> >> # let loop f a = >> let rec (b, c) = f (a, c) in >> b;; >> Characters 25-31: >> let rec (b, c) = f (a, c) in >> ^^^^^^ >> Only variables are allowed as left-hand side of `let rec' >> >> So I try to bypass this restriction: >> >> # let loop f a = >> let rec couple = f (a, snd couple) in >> fst couple;; >> Characters 34-51: >> let rec couple = f (a, snd couple) in >> ^^^^^^^^^^^^^^^^^ >> This kind of expression is not allowed as right-hand side of `let rec' >> >> >> Any ideas about what is this restriction, an what is it for? > > Ocaml has call-by-value, and it cannot figure out a value to be passed > as f's second argument. To be convinced, just imagine that the type of > this argument is empty (an empty type can be introduced by "type empty" > without definition, for instance). > > -- > Jean-Christophe > > > > ------------------------------ > > _______________________________________________ > Caml-list mailing list. Subscription management: > http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list > Archives: http://caml.inria.fr > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > Bug reports: http://caml.inria.fr/bin/caml-bugs > > > End of Caml-list Digest, Vol 32, Issue 71 > *****************************************