caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* Local opening of modules
@ 1998-10-27 20:35 John Prevost
  1998-11-10 16:04 ` Anton Moscal
  0 siblings, 1 reply; 7+ messages in thread
From: John Prevost @ 1998-10-27 20:35 UTC (permalink / raw)
  To: caml-list

This is a question that I found asked back in the logs, but which I
found no answer to:

Is there any good reason that Caml doesn't have a mechanism like SML's
to open a module locally?  For example:

let open Num in
let a = num_of_int 2739 in
let b = num_of_int 234 in
let bar = a +/ b;;

an even better example would be one in which the symbol "+/" was
actually "+", like in the SML bignum package.  A friend of mine used
this mechanism quite well in a project where bignum math was used in
only a few restricted places.  The rest of the file didn't need to be
polluted namespace-wise with the bignum package (and if there were, say,
another package that wanted +/ it wouldn't cause problems...  There are
only so many reasonable versions of + you can make without getting into
collision problems, after all.)

Maybe there's a technical constraint in the way Caml is organized that
keeps this from being done?

jmp





^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Local opening of modules
  1998-10-27 20:35 Local opening of modules John Prevost
@ 1998-11-10 16:04 ` Anton Moscal
  1998-11-10 21:22   ` John Prevost
  0 siblings, 1 reply; 7+ messages in thread
From: Anton Moscal @ 1998-11-10 16:04 UTC (permalink / raw)
  To: John Prevost; +Cc: caml-list

On Tue, 27 Oct 1998, John Prevost wrote:

> This is a question that I found asked back in the logs, but which I
> found no answer to:
> 
> Is there any good reason that Caml doesn't have a mechanism like SML's
> to open a module locally?  For example:
> 
> let open Num in
> let a = num_of_int 2739 in
> let b = num_of_int 234 in
> let bar = a +/ b;;
> 
[...]
> 
> Maybe there's a technical constraint in the way Caml is organized that
> keeps this from being done?
> 

With CamlP4 preprocessor (tool for syntax extension of Ocaml) I got
this effect by the following grammar extension:

====cut====
let (uniq_lid, uniq_uid) = 
    let cnt = ref 0 in
    (incr cnt; fun () -> Printf.sprintf "l_uniq_id_%d" !cnt),
    (incr cnt; fun () -> Printf.sprintf "U_uniq_id_%d" !cnt)

EXTEND
  expr: LEVEL "expr1"
  [[
    "let"; "open"; path = LIST1 UIDENT SEP "."; "in"; e = expr LEVEL "top" ->
    	let temp = uniq_uid () 
    	and res  = uniq_lid ()
    	in
      	<:expr< let module $temp$ = 
      	   struct open $path$; value $lid:res$ = $e$; end in $uid:temp$.$lid:res$
      	>>
  ]];
END
====cut====
After making these changes you can write in your program something like:
====cut====
module M = struct 
	module N = struct let x = 1 end;;
end

let x = let open M.N in x
====cut====

Regards,
Anton




^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Local opening of modules
  1998-11-10 16:04 ` Anton Moscal
@ 1998-11-10 21:22   ` John Prevost
  1998-11-25 15:17     ` Objects as sums Anton Moscal
  0 siblings, 1 reply; 7+ messages in thread
From: John Prevost @ 1998-11-10 21:22 UTC (permalink / raw)
  To: Anton Moscal; +Cc: caml-list

On Tue, 10 Nov 1998, Anton Moscal wrote:

> With CamlP4 preprocessor (tool for syntax extension of Ocaml) I got
> this effect by the following grammar extension:
  {...}

Interesting.  I hadn't realized that you could define modules inside let
statements like this:

let f x = 
  let module M = struct
                   open Foo;;
                   let v = x + x
                 end
  in M.v

(which is exactly what you're doing...)

Actually, the non-sugared form I've written above is pretty satisfactory
all by itself, although not as clean looking as the sugared-up camlp4
stuff.

Thanks!

John.





^ permalink raw reply	[flat|nested] 7+ messages in thread

* Objects as sums
  1998-11-10 21:22   ` John Prevost
@ 1998-11-25 15:17     ` Anton Moscal
  1998-11-26 15:58       ` Didier Remy
  0 siblings, 1 reply; 7+ messages in thread
From: Anton Moscal @ 1998-11-25 15:17 UTC (permalink / raw)
  To: caml-list

Hello!

I try to write in O'Caml a well-known idiom of OO for simulating disjoint
sum of types by virtual methods and inheritance: working example in C++:

+++++++++
#include <stdlib.h>
class B; class C;
class A { public: 
  virtual B * b () { abort (); return 0; } 
  virtual C * c () { abort (); return 0; } 
};

class B { public: virtual B * b () { return this; } };
class C { public: virtual C * c () { return this; } };
--------
but, when I write the same program in O'Caml:
++++++++
class a = object (self)
  method b () = ((assert false): b)
  method c () = ((assert false): c)
end

and b = object (self)
  inherit a
  method b () = self
end

and c = object (self)
  inherit a
  method c () = self
end
-------
It doesn't work (with diagnostics `self type can't escape from it's
scope'). The following question arises: either this idiom can't be
expressed in O'Caml or I'm fool :) and is it possible to do it by any way?

Regards,
Anton E. Moscal




^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Objects as sums
  1998-11-25 15:17     ` Objects as sums Anton Moscal
@ 1998-11-26 15:58       ` Didier Remy
  1998-11-28 10:46         ` Anton Moscal
  0 siblings, 1 reply; 7+ messages in thread
From: Didier Remy @ 1998-11-26 15:58 UTC (permalink / raw)
  To: Anton Moscal; +Cc: caml-list

> class a = object (self)
>   method b () = ((assert false): b)
>   method c () = ((assert false): c)
> end

Here the type of method b is a (the type of objects of class a)

> and b = object (self)
>   inherit a
>   method b () = self
> end

The type of self is not the type a, since self may be an object ofa subclass
of a (imagine you are calling method b from a subclass of b).  The system
tries to unify the type of self with a, and then fails.

One solution at this point is to write class b as follows:

    class b = object (self)
      inherit a
      method b () = (self : #a :> a)
    end;;

so that extra methods are hidden and self can be seem with type a.
However, it would have been better to define a as follows (which is probably
what you meant):

class a = object (self : 'a)
  method b () = ((assert false): 'a)
  method c () = ((assert false): 'a)
end;;

Here, the methods b and c return an object of the same type as their own
type. In particular, in a subclass, they will return an object of the type
of objects of the subclass...

Then, the rest of the example works unchanged.

    class c = object (self)
      inherit a
      method c () = self
    end;;

-Didier.




^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Objects as sums
  1998-11-26 15:58       ` Didier Remy
@ 1998-11-28 10:46         ` Anton Moscal
  1998-11-30 12:35           ` Jerome Vouillon
  0 siblings, 1 reply; 7+ messages in thread
From: Anton Moscal @ 1998-11-28 10:46 UTC (permalink / raw)
  To: Didier.Remy; +Cc: caml-list

On Thu, 26 Nov 1998, Didier Remy wrote:

> class a = object (self : 'a)
>   method b () = ((assert false): 'a)
>   method c () = ((assert false): 'a)
> end;;
> 
> Here, the methods b and c return an object of the same type as their own
> type. In particular, in a subclass, they will return an object of the type
> of objects of the subclass...
> 
> Then, the rest of the example works unchanged.
> 
>     class c = object (self)
>       inherit a
>       method c () = self
>     end;;

This is not solution of my task. I want to simulate by ocaml classes the
following C++ program:

# include <stdlib.h>

enum {NODE, LEAF};
class Node;
class Leaf;
class Tree { public:
  virtual int tag () = 0;
  virtual Node * node () { abort (); return 0; }
  virtual Leaf * leaf () { abort (); return 0; }
};

class Leaf: public Tree { public:
  int val;
  int tag () { return LEAF; }
  Leaf * leaf () { return this; }
};

class Node: public Tree { public:
  Tree * l, * r;
  int tag () { return NODE; }
  Node * node () { return this; }
};

int sum (Tree * tree)
{
  switch (tree -> tag ()) 
    {
    case LEAF: return tree -> leaf () -> val;
    case NODE: return sum (tree -> node () -> l) + sum (tree -> node () -> r);
    }
}

This program may be easily translated to ocaml as follows:

type tree = Leaf of int | Tree of tree * tree
let rec sum = function
    Leaf v -> v
  | Tree (l, r) -> sum l + sum r

but I would like to have solution with classes.

Your proposals do not work: type of (tree#node ()) will have `tree' type
and will fail on selection of a method, specific for node.

PS: this trick implements type-safe conversion down to objects hierarchy.
    Question of my interest is the following: whether such
    conversion is possible or not?

Regards, 
Anton




^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Objects as sums
  1998-11-28 10:46         ` Anton Moscal
@ 1998-11-30 12:35           ` Jerome Vouillon
  0 siblings, 0 replies; 7+ messages in thread
From: Jerome Vouillon @ 1998-11-30 12:35 UTC (permalink / raw)
  To: Anton Moscal, Didier.Remy; +Cc: caml-list

On Sat, Nov 28, 1998 at 01:46:12PM +0300, Anton Moscal wrote:

[...]
> This is not solution of my task. I want to simulate by ocaml classes the
> following C++ program:
> 
> # include <stdlib.h>
> 
> enum {NODE, LEAF};
> class Node;
> class Leaf;
> class Tree { public:
>   virtual int tag () = 0;
>   virtual Node * node () { abort (); return 0; }
>   virtual Leaf * leaf () { abort (); return 0; }
> };
> 
> class Leaf: public Tree { public:
>   int val;
>   int tag () { return LEAF; }
>   Leaf * leaf () { return this; }
> };
> 
> class Node: public Tree { public:
>   Tree * l, * r;
>   int tag () { return NODE; }
>   Node * node () { return this; }
> };
> 
> int sum (Tree * tree)
> {
>   switch (tree -> tag ()) 
>     {
>     case LEAF: return tree -> leaf () -> val;
>     case NODE: return sum (tree -> node () -> l) + sum (tree -> node () -> r);
>     }
> }
>
[...]
> 
> PS: this trick implements type-safe conversion down to objects hierarchy.
>     Question of my interest is the following: whether such
>     conversion is possible or not?

Yes, it is possible to translate the program into Ocaml.

The difficulty you have probably encounter is that in class "leaf",
for instance, the type of self is not "leaf", but a more general type.
The implementation of method "full_object" below must therefore
contain a coercion. As it is not possible to coerce to a type that is
not yet completely defined (this is the case for type "leaf" at this
point), I used an extra class "leaf_intf" to provide a type for the
coercion.

I have used a single method "full_object" rather than two methods
"node" and "leaf". This way, there is no need to raise any
exception. But this change was not necessary.

Regards,

-- Jérôme

type ('a, 'b) alt = First of 'a | Second of 'b;;

class virtual tree = object
  method virtual full_object : (leaf_intf, node_intf) alt
end and virtual leaf_intf = object
  inherit tree
  method virtual v : int
end and virtual node_intf = object
  inherit tree
  method virtual l : tree
  method virtual r : tree
end;;

class leaf v0 = object (self)
  inherit leaf_intf
  method full_object = First (self :> leaf_intf)
  method v = v0
end;;

class node l0 r0 = object (self)
  inherit node_intf
  method full_object = Second (self :> node_intf)
  method l :> tree = l0
  method r :> tree = r0
end;;

let rec sum t =
  match t#full_object with
    First t' ->
      t'#v
  | Second t' ->
      sum (t'#l) + sum (t'#r);;

# sum (new node (new leaf 3) (new node (new leaf 1) (new leaf 2)) :> tree);;
- : int = 6




^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~1998-11-30 18:39 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1998-10-27 20:35 Local opening of modules John Prevost
1998-11-10 16:04 ` Anton Moscal
1998-11-10 21:22   ` John Prevost
1998-11-25 15:17     ` Objects as sums Anton Moscal
1998-11-26 15:58       ` Didier Remy
1998-11-28 10:46         ` Anton Moscal
1998-11-30 12:35           ` Jerome Vouillon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).