Version française
Home     About     Download     Resources     Contact us    
Browse thread
Objects contrib
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Fabrice Le Fessant <fessant@p...>
Subject: Re: Objects contrib: new URL ...

> A slight improvement: I would rather have cast raise Match_failure
> than a standard Failure.  In particular with a match failure you have
> position information for where it failed.

At the end of this message, you will find a patch to apply on
patch.cast to raise a Oo.CastFailure exception with the information
on the file and the line number where the exception was raised.

>  Lots of people want such a feature. This is standard in
> LISP or JAVA, so why not in Caml?

>  I believe this really goes against what ML is trying to be.

In every language, there is a compromise to do between expressiveness
and static verification of programs (by typing for example). I think
that a great quality of Objective-Caml is that it has reached a very
good compromise, and that each user can decide whether it is most
interested in the safety of the language -- for programing provers or
compilers for example -- or by the ease of programing in this language
-- for fast prototyping, or system programing. In both cases, he will
benefit from all the qualities of the language.

In our case, the "cast" construct for the object-oriented programing
style can be compared to the "ref" or the "array" types for the
imperative programming style. Both can lead to "unsafe" programs
(should the compiler allow "x.(-1)" in a program as it currently does?), 
but they can still be useful when used carefully. In that way, I trust
Ocaml users (demagogy :)).

With this patch, I tried to increase the expressiveness of the language,
without breaking its safety. In this way, I think it is still better
than using Obj.magic, since the "implements" checks whether the types
can correctly be coerced. 

> Remark:
> You can already implement something similar inside the language:

Can you really use an object (mutable) as the key in the hashtbl (its
hash value may change when it is modified ?) ?

Regards,

- Fabrice

*** tmp/patch.cast	Thu Jun 17 09:06:44 1999
--- tmp2/patch.cast	Thu Jun 17 09:05:52 1999
***************
*** 4,8 ****
  ***************
  *** 442,447 ****
! --- 442,450 ----
          event_after e (Lsend(Lvar met_id, transl_exp expr, []))
      | Texp_new (cl, _) ->
--- 4,8 ----
  ***************
  *** 442,447 ****
! --- 442,453 ----
          event_after e (Lsend(Lvar met_id, transl_exp expr, []))
      | Texp_new (cl, _) ->
***************
*** 10,14 ****
  +   | Texp_cast (exp, cl_path, cl_decl) ->
  +       Lapply(Translobj.oo_prim "class_cast",
! +         [transl_exp exp; transl_path cl_path])
      | Texp_instvar(path_self, path) ->
          Lprim(Parrayrefu Paddrarray, [transl_path path_self; transl_path path])
--- 10,17 ----
  +   | Texp_cast (exp, cl_path, cl_decl) ->
  +       Lapply(Translobj.oo_prim "class_cast",
! +         [transl_exp exp; transl_path cl_path;
! +         Lconst (Const_base(Const_string (
! +               Printf.sprintf "File %s: char %d" !Location.input_name
! +                 e.exp_loc.Location.loc_start)))])
      | Texp_instvar(path_self, path) ->
          Lprim(Parrayrefu Paddrarray, [transl_path path_self; transl_path path])
***************
*** 257,265 ****
  ***************
  *** 478,480 ****
! --- 487,500 ----
           done;
           print_newline ())
        (sort_buck !bucket_list)
! + 
  +   
  + let class_implements cl1 cl2 = 
--- 260,269 ----
  ***************
  *** 478,480 ****
! --- 487,501 ----
           done;
           print_newline ())
        (sort_buck !bucket_list)
! +
! + exception CastFailure of string
  +   
  + let class_implements cl1 cl2 = 
***************
*** 268,275 ****
  +   t1.casts <- t2 :: t1.casts
  +   
! + let class_cast o cl =
  +   let t1 = (magic (field (field o 0) 0): table) in
  +   let t2 = cl.table in
! +   if List.memq t2 t1.casts then o else failwith "Cast failure"
  diff -r -C 3 ocaml-2.02/stdlib/oo.mli csl/stdlib/oo.mli
  *** ocaml-2.02/stdlib/oo.mli	Sun Aug 16 23:28:41 1998
--- 272,279 ----
  +   t1.casts <- t2 :: t1.casts
  +   
! + let class_cast o cl location =
  +   let t1 = (magic (field (field o 0) 0): table) in
  +   let t2 = cl.table in
! +   if List.memq t2 t1.casts then o else raise (CastFailure location)
  diff -r -C 3 ocaml-2.02/stdlib/oo.mli csl/stdlib/oo.mli
  *** ocaml-2.02/stdlib/oo.mli	Sun Aug 16 23:28:41 1998
***************
*** 277,287 ****
  ***************
  *** 68,70 ****
! --- 68,73 ----
        distrib : int array; small_bucket_count: int; small_bucket_max: int }
    val stats: unit -> stats
    val show_buckets: unit -> unit
  + 
  + val class_implements : class_info -> class_info -> unit
! + val class_cast : Obj.t -> class_info -> Obj.t
  diff -r -C 3 ocaml-2.02/typing/typecore.ml csl/typing/typecore.ml
  *** ocaml-2.02/typing/typecore.ml	Fri Feb 12 13:34:32 1999
--- 281,292 ----
  ***************
  *** 68,70 ****
! --- 68,74 ----
        distrib : int array; small_bucket_count: int; small_bucket_max: int }
    val stats: unit -> stats
    val show_buckets: unit -> unit
  + 
+ + exception CastFailure of string
  + val class_implements : class_info -> class_info -> unit
! + val class_cast : Obj.t -> class_info -> string -> Obj.t
  diff -r -C 3 ocaml-2.02/typing/typecore.ml csl/typing/typecore.ml
  *** ocaml-2.02/typing/typecore.ml	Fri Feb 12 13:34:32 1999