Version française
Home     About     Download     Resources     Contact us    
Browse thread
Re: Caml-list Digest, Vol 32, Issue 71
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Netconsult International <netconsult@h...>
Subject: Re: Caml-list Digest, Vol 32, Issue 71
please remove my adress from you list

Best regards
----- Original Message ----- 
From: <caml-list-request@yquem.inria.fr>
To: <caml-list@yquem.inria.fr>
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 <berke.durak@exalead.com>
> Subject: [Caml-list] Objects, dynamic cast, Obj.magic abuse and
> dragons
> To: Caml-list List <caml-list@inria.fr>
> 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 <rich@annexia.org>
> Subject: Re: [Caml-list] Objects, dynamic cast, Obj.magic abuse and
> dragons
> To: Berke Durak <berke.durak@exalead.com>
> Cc: Caml-list List <caml-list@inria.fr>
> 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" <loup.vaillant@gmail.com>
> Subject: [Caml-list] Unexpected restriction in "let rec" expressions
> To: "Caml List" <caml-list@inria.fr>
> 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 <kattlachan@gmail.com>
> Subject: Re: [Caml-list] Objects, dynamic cast, Obj.magic abuse and
> dragons
> To: "Berke Durak" <berke.durak@exalead.com>
> Cc: Caml-list List <caml-list@inria.fr>
> Message-ID:
> <6ebe51ce0802260448i61b968e4tf618edc0580636f5@mail.gmail.com>
> Content-Type: text/plain; charset=UTF-8
>
> Hi,
>
> 2008/2/26 Berke Durak <berke.durak@exalead.com>:
>>  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 <berke.durak@exalead.com>
> Subject: Re: [Caml-list] Objects, dynamic cast, Obj.magic abuse and
> dragons
> Cc: Caml-list List <caml-list@inria.fr>
> 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 <Jean-Christophe.Filliatre@lri.fr>
> Subject: Re: [Caml-list] Unexpected restriction in "let rec"
> expressions
> To: Loup Vaillant <loup.vaillant@gmail.com>
> Cc: Caml List <caml-list@inria.fr>
> 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
> *****************************************