Re: Objects contrib: new URL ...

From: Fabrice Le Fessant (fessant@pa.dec.com)
Date: Thu Jun 17 1999 - 19:16:32 MET DST


From: Fabrice Le Fessant <fessant@pa.dec.com>
Date: Thu, 17 Jun 1999 10:16:32 -0700 (PDT)
To: Jacques GARRIGUE <garrigue@kurims.kyoto-u.ac.jp>
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



This archive was generated by hypermail 2b29 : Sun Jan 02 2000 - 11:58:23 MET