Version française
Home     About     Download     Resources     Contact us    
Browse thread
typing of a class
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Benoit Deboursetty <debourse@e...>
Subject: Re: typing of a class
> I've been using the OO features of Caml these past days, and soon
> observed a behavior of the typing system that I don't understand. Here
> is a simplified version of my problem:
> 
> # class a (arg : a -> b) = object(self)
>     val ob = arg self
>   end
>   and b = object
>   end;;
> 
> The instance variable self
> cannot be accessed from the definition of another instance variable
> 
> I don't understand why it is forbidden for an object to pass itself to
> another one (which is possible in Java or Eiffel for example). Could
> someone explain me? Or is there a paper talking about this?

Ce n'est pas parce que l'objet se passe à un autre qu'une erreur est
détectée... Mais parce que les variables d'instance ne peuvent pas se
faire récursivement référence.

Les variables d'instance sont celles qui sont propres à chaque instance de
l'objet. Elles sont construites, à l'exécution, les unes après les autres
dans un ordre non spécifié (sauf "self", qui est toujours la dernière, je
suppose...) Dans votre cas, "self" et "ob" sont des variables d'instance
de la classe a.

Par exemple, imaginez que le système soit au moment de construire la
première variable d'instance d'un objet, mais que pour la construire il
ait besoin des autres variables d'instance...

[J'ai l'impression que c'est le même genre de raison qui empêche (pour le
moment ?) d'avoir des dépendances cycliques entre modules et des
applications de fonctions dans les membres droits des "let rec" (et là
j'interroge l'équipe de caml...)]

Le problème apparaît si la fonction que vous passez en argument fait accès
aux méthodes de self. Modifions un peu votre exemple, en faisant
l'hypothèse que le compilateur accepte le code suivant :

# class a (arg : a -> int) = object (self)
    val ob = arg self
    method get_ob = ob
  end;;

# let bad_arg = fun x -> ignore (x#get_ob); 0;;

# let instance_of_a = new a bad_arg;;

Que se passe-t-il à la construction de l'instance "instance_of_a" ? En y
réfléchissant un tout petit peu, vous verrez très vite qu'il va forcément
y avoir un pointeur invalide déréférencé (dans "bad_arg", "x#get_ob").

---

It is not especially forbidden to an object to pass itself to another one.

The error message means that you cannot recursively nest instance variable
declarations. Instance variable means variable that are built with each
instance of an object; here, ob and self are instance variable (they are
different for each object). When you call "new", the instance variables 
are built one after the other in a non specified order (except that self
is always the last one I suppose). Suppose for example the runtime builds
the first instance variable, but that instance variable depends on other
instance variable that will only be built later. This is clearly a
safeness pitfall!

(I think it is the same kind of problem that leads to a difficulty in
recursively nesting modules and "right side of let rec" problems?)

Let me somewhat modify your example to show you more concretely the point
of the error and assume the compiler accept this:

# class a (arg : a -> int) = object (self)
    val ob = arg self
    method get_ob = ob
  end

# let bad_arg = fun x -> ignore (x#get_ob); 0;;

# let instance_of_a = new a bad_arg;;

If you only imagine the building of an instance of that object, you will
soon see that an invalid pointer is going to be dereferenced no matter
what is the runtime implementation.

Best regards,
Benoit de Boursetty.