caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* porté des définitions des variables de classe
@ 1998-10-05 15:10 Serge Fantino
  1998-10-06 12:35 ` port des d finitions " Sylvain BOULM'E
  0 siblings, 1 reply; 10+ messages in thread
From: Serge Fantino @ 1998-10-05 15:10 UTC (permalink / raw)
  To: caml-list; +Cc: Vyskocil Vladimir, caml-light

Ocaml-2.0 autorise la déclaration de classe suivante:

class test =
object
    val v = [|Random.int 1000|]
    method get = v.(1)
    method set x = v.(1)<-x
end

Bizarrement, les objets créés à partir de cette définition semblent
tous partager la meme variable v:

let a = new test;;
let b = new test;;

a#get;;
b#get;;
(* retourne la meme valeur *)

a#set (Random.int 1000);;
a#get;;
b#get;;
(* a et b sont tous les 2 modifiés *)

Si l'on déclare la classe différement:

class test () =
...

alors tout redevient "normal".

Est-ce que c'est un bug ? Ou est-ce une nouvelle fonctionnalitée ?


Serge Fantino






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

* Re: port des d finitions des variables de classe
  1998-10-05 15:10 porté des définitions des variables de classe Serge Fantino
@ 1998-10-06 12:35 ` Sylvain BOULM'E
  1998-10-06 16:12   ` porte des definitions " Serge Fantino
  0 siblings, 1 reply; 10+ messages in thread
From: Sylvain BOULM'E @ 1998-10-06 12:35 UTC (permalink / raw)
  To: Serge Fantino; +Cc: caml-list, Vyskocil Vladimir, caml-light

Bonjour,

Il me semble que c'est dans la semantique des classes
de Ocaml, qui supportent desormais les "variables statiques de classes"
partagees par tous les objets de la classe. (Les gens de Ocaml me
corrigeront ...)

Ainsi,

class test1 =
object
    val v = ref 5
    method get = !v
    method set x = v:=x
end;;

est equivalent a

class test1 = let v1=ref 5 in
object
    val v=v1
    ...


Dans les 2 cas,

let a=new test1 and b=new test1 in (b#set 4; a#get);;

retourne 4.



Par contre c'est different de 

class test2 () = let v1=ref 5 in
object
    val v=v1
    ...

let a=new test2 () and b=new test2 () in (b#set 4; a#get);;

retourne 5.


Encore mieux,

let f=new test2;;
retourne 
val f : unit -> test2 = <fun>

Une classe sert en fait a generer (au travers du new) des fonctions
a valeur dans les objets (de cette classe). Et comme pour les autres
fonctions de Caml, on a la possibilite d'utiliser des variables locales...


Sylvain.



PS: j'aurai pu ecrire aussi test2 sous la forme

class test2 () =
object 
  val v=ref 5
  ...


Il est aussi interessant de remarquer que

class test3 =
object
    val mutable v = 5
    method get = v
    method set x = v<-x
end;;

let a = new test3 and b=new test3 in (b#set 4; a#get);;

retourne 5







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

* Re: porte des definitions des variables de classe
  1998-10-06 12:35 ` port des d finitions " Sylvain BOULM'E
@ 1998-10-06 16:12   ` Serge Fantino
  1998-10-07  7:30     ` Pierre Weis
  1998-10-07 10:16     ` porte des definitions " Sylvain BOULM'E
  0 siblings, 2 replies; 10+ messages in thread
From: Serge Fantino @ 1998-10-06 16:12 UTC (permalink / raw)
  To: Sylvain BOULM'E; +Cc: caml-list, Vyskocil Vladimir

Sylvain BOULM'E wrote:

> Bonjour,
>
> Il me semble que c'est dans la semantique des classes
> de Ocaml, qui supportent desormais les "variables statiques de classes"
> partagees par tous les objets de la classe. (Les gens de Ocaml me
> corrigeront ...)
>
> Ainsi,
>
> class test1 =
> object
>     val v = ref 5
>     method get = !v
>     method set x = v:=x
> end;;
>
> est equivalent a
>
> class test1 = let v1=ref 5 in
> object
>     val v=v1
>     ...
>
> Dans les 2 cas,
>
> let a=new test1 and b=new test1 in (b#set 4; a#get);;
>
> retourne 4.
>

Effectivement, OCaml-2.0 semble fonctionné suivant ce schéma.
Je trouve cette "nouveauté" embarrassante:

- elle est ambigue;
Cela va a l'encontre du "sens commun". Les variables d'instance sont
declarees dans "object": je m'attends donc a ce que la porté de la variable
soit locale à une instance de la classe.
Lorsque je declare:

class test1 =
object
    val v = ref 5
    method get = !v
    method set x = v:=x
end;;

je m'attends a ce que la variable v soit locale à chaque nouvel objet
construit à partir de (new test1).
D'ailleurs, il est confondant de voir que la déclaration suivante:

class test3 =
object
    val mutable v = 5
    method get = v
    method set x = v<-x
end;;

se comporte différement de test1 !

- elle n'est pas consistante
Rien ne me previent du changement de fonctionnalité dans ce cas particulier.
Il suffit de supprimer ou d'ajouter un paramètre à une classe pour en changer
complètement la sémantique.
Si je redefinis test1 :

class test1 (x:int) =
object
    val v = ref x
    method get = !v
    method set x = v:=x
end;;

alors la variable v n'est plus partagée...

- elle n'est pas necessaire;
Si on en a besoin, on peut simplement partager des variables "statiques"
entre différentes instances de la meme classe.

Enfin c'est mon avis d'utilisateur. Pour la petite histoire, il m'a fallu
tout un weekend pour comprendre pourquoi mon code ne marchait plus sous
OCaml-2.0, alors que la version 1.07 marche tres bien...



Objectivement votre,

    Serge Fantino

> Par contre c'est different de
>
> class test2 () = let v1=ref 5 in
> object
>     val v=v1
>     ...
>
> let a=new test2 () and b=new test2 () in (b#set 4; a#get);;
>
> retourne 5.
>
> Encore mieux,
>
> let f=new test2;;
> retourne
> val f : unit -> test2 = <fun>
>
> Une classe sert en fait a generer (au travers du new) des fonctions
> a valeur dans les objets (de cette classe). Et comme pour les autres
> fonctions de Caml, on a la possibilite d'utiliser des variables locales...

> Sylvain.
>
> PS: j'aurai pu ecrire aussi test2 sous la forme
>
> class test2 () =
> object
>   val v=ref 5
>   ...
>
> Il est aussi interessant de remarquer que
>
> class test3 =
> object
>     val mutable v = 5
>     method get = v
>     method set x = v<-x
> end;;
>
> let a = new test3 and b=new test3 in (b#set 4; a#get);;
>
> retourne 5







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

* Re: porte des definitions des variables de classe
  1998-10-06 16:12   ` porte des definitions " Serge Fantino
@ 1998-10-07  7:30     ` Pierre Weis
  1998-10-07 13:03       ` porte des definitions / initialisation " Serge Fantino
  1998-10-07 10:16     ` porte des definitions " Sylvain BOULM'E
  1 sibling, 1 reply; 10+ messages in thread
From: Pierre Weis @ 1998-10-07  7:30 UTC (permalink / raw)
  To: Serge Fantino; +Cc: caml-list

> Sylvain BOULM'E wrote:
> 
> > Bonjour,
> >
> > Il me semble que c'est dans la semantique des classes
> > de Ocaml, qui supportent desormais les "variables statiques de classes"
> > partagees par tous les objets de la classe. (Les gens de Ocaml me
> > corrigeront ...)
> >
> > Ainsi,
> >
> > class test1 =
> > object
> >     val v = ref 5
> >     method get = !v
> >     method set x = v:=x
> > end;;
> >
> > est equivalent a
> >
> > class test1 = let v1=ref 5 in
> > object
> >     val v=v1
> >     ...
> >
> > Dans les 2 cas,
> >
> > let a=new test1 and b=new test1 in (b#set 4; a#get);;
> >
> > retourne 4.
> >
> 
> Effectivement, OCaml-2.0 semble fonctionné suivant ce schéma.
> Je trouve cette "nouveauté" embarrassante:

Je ne comprends pas le problème: cela ressemble fort à la sémantique
habituelle du Caml de base...

> - elle est ambigue;

Je ne vois pas non plus en quoi elle l'est. Je ne connais pas grand
chose aux objets mais ce comportement était celui que je prévoyais:
la référence ref 5 est partagée dans les deux cas, comme dans le
langage de base ...

> Cela va a l'encontre du "sens commun". Les variables d'instance sont
> declarees dans "object": je m'attends donc a ce que la porté de la variable
> soit locale à une instance de la classe.

C'est le cas. Je ne comprends pas. Ne confondez-vous pas partage des
valeurs et portée des identificateurs ou variables ?

> Lorsque je declare:
> 
> class test1 =
> object
>     val v = ref 5
>     method get = !v
>     method set x = v:=x
> end;;
> 
> je m'attends a ce que la variable v soit locale à chaque nouvel objet
> construit à partir de (new test1).

C'est le cas. Seulement vous avez tout fait pour partager la référence
ref 5: pas de paramètre à la classe donc calcul fait une fois pour
toutes donc allocation unique donc partage. À quoi d'autre
pourrions-nous nous attendre ?

> D'ailleurs, il est confondant de voir que la déclaration suivante:
> 
> class test3 =
> object
>     val mutable v = 5
>     method get = v
>     method set x = v<-x
> end;;
> 
> se comporte différement de test1 !

Absolument pas. Il est rassurant que ça se comporte d'une façon
différente, puisque maintenant la variable v est mutable!

> - elle n'est pas consistante
> Rien ne me previent du changement de fonctionnalité dans ce cas
> particulier.

Bien sûr que si: c'est cohérent car compatible avec toute la
sémantique du langage de base (donc in fine avec celle de la réduction
faible du lambda-calcul en appel par valeur). Enfin tout vous prévient
de la différence entre les exemples: la présence du mot-clé mutable,
l'absence de paramètre à la classe, le let ... in pour la deuxième
version. 

> Il suffit de supprimer ou d'ajouter un paramètre à une classe pour en changer
> complètement la sémantique.
> Si je redefinis test1 :
> 
> class test1 (x:int) =
> object
>     val v = ref x
>     method get = !v
>     method set x = v:=x
> end;;
> 
> alors la variable v n'est plus partagée...

Bien entendu. Rien d'étonnant là-dedans. Avez-vous remarqué combien la
sémantique d'une fonction change quand on modifie son nombre de
paramètres ? En particulier lorsqu'une fonction passe de 1 à zéro
paramètres comme c'est le cas ici ?

Comparez par exemple:

let f () = exit 0;;

let f = exit 0;;

Vous devriez observer une différence de sémantique certaine. Remplacez
classe par fonction dans votre phrase et vous obtenez:

``Il suffit de supprimer ou d'ajouter un paramètre à une fonction pour
en changer complètement la sémantique.''

Il me semble que ce problème de paramètre ajouté ou suprimé est
général à beaucoup de constructions du langage.

Blague: disons-le en Caml !

let étonnement = function construction ->
  "Il suffit de supprimer ou d'ajouter un paramètre à " ^ construction ^
  " pour en changer complètement la sémantique.";;

étonnement "une classe";;
étonnement "une fonction";;
étonnement "un module";;
étonnement "un foncteur";;
étonnement "un type";;

etc..

> - elle n'est pas necessaire;
> Si on en a besoin, on peut simplement partager des variables "statiques"
> entre différentes instances de la meme classe.

Je laisse la parole aux spécialistes des objets.

> Enfin c'est mon avis d'utilisateur.

Et il est très intéressant. Merci de nous le faire partager. Je crois
qu'il montre aux implémenteurs de Caml qu'il y a sans doute un décifit
d'explications sur le langage en général et sur ses objets en particulier.

> Pour la petite histoire, il m'a fallu
> tout un weekend pour comprendre pourquoi mon code ne marchait plus sous
> OCaml-2.0, alors que la version 1.07 marche tres bien...

Peut-être encore ce déficit d'explications ...

> Objectivement votre,
> 
>     Serge Fantino

Cordialement,

Pierre Weis

INRIA, Projet Cristal, Pierre.Weis@inria.fr, http://cristal.inria.fr/~weis/







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

* Re: porte des definitions des variables de classe
  1998-10-06 16:12   ` porte des definitions " Serge Fantino
  1998-10-07  7:30     ` Pierre Weis
@ 1998-10-07 10:16     ` Sylvain BOULM'E
  1998-10-08  7:33       ` Jacques GARRIGUE
  1 sibling, 1 reply; 10+ messages in thread
From: Sylvain BOULM'E @ 1998-10-07 10:16 UTC (permalink / raw)
  To: Serge Fantino; +Cc: Sylvain BOULM'E, caml-list, Vyskocil Vladimir

Bonjour,

> - elle est ambigue;
> Cela va a l'encontre du "sens commun". 

C'est vrai que ca peut sembler bizarre, mais je trouve 
cela assez coherent avec le reste de Ocaml.

Par exemple :

 let toto = let a=ref 0 in function () -> (a:=!a+1; !a)
 in (toto (); toto ());;

retourne 2

Alors que

 let tutu () = let a=ref 0 in function () -> (a:=!a+1; !a);;
 in (tutu () (); tutu () ());;

retourne 1

> D'ailleurs, il est confondant de voir que la déclaration suivante:
> class test3 > object
>     val mutable v = 5
>     method get = v
>     method set x = v<-x
> end;;

Il ne faut pas confondre variable mutable et reference. Une reference
est un "record" avec un champ mutable. 
  # ref 1;;
  - : int ref = {contents=1}
Donc si dans "let v=ref 1", v designe ce "record" et non pas le champ 
"mutable".

> Il suffit de supprimer ou d'ajouter un paramètre à une classe pour en changer
> complètement la sémantique.

C'est pareil pour "tutu" et "toto".

> - elle n'est pas consistante
> Rien ne me previent du changement de fonctionnalité dans ce cas particulier.
> Il suffit de supprimer ou d'ajouter un paramètre à une classe pour en changer
> complètement la sémantique.

> - elle n'est pas necessaire;
> Si on en a besoin, on peut simplement partager des variables "statiques"
> entre différentes instances de la meme classe.

> Enfin c'est mon avis d'utilisateur. Pour la petite histoire, il m'a fallu
> tout un weekend pour comprendre pourquoi mon code ne marchait plus sous
> OCaml-2.0, alors que la version 1.07 marche tres bien...

D'abord, sous Ocaml 1.07, on devait obligatoirement mettre un argument
a une classe : si on conserve cet argument, les classes Ocaml-2.0 se
comportent de la meme facon. Les classes de Ocaml-2.0 sont en fait plus
generales que celles de Ocam 1.07

En fait, pour eviter ces possibles confusions, je pense qu'on ne devrait
utiliser les variables d'instances "val" que vraiment quand elles sont des 
variables d'instances (ie quand elles sont destinees a evoluer, de facon
"imperative" ou "fonctionnelle", par copie d'objet). Sur mes exemples
precedents, on devrait ecrire test1 comme cela :
 
 class test1 = 
   let v=ref 5 in
    object
      method get= !v
      method set x= v:=x
    end;;


Par contre, il est vrai que je trouve surprenant que :

  class test2     let v=ref 5
    in fun () -> 
          object 
            method get = !v
            method set x = v:= x
         end;;

  let f=new test2 in 
    let a=f() and b=f() in (b#set 4; a#get);;

retourne 5

au lieu de retourner 4, comme on s'y attenderait....



Sylvain.






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

* Re: porte des definitions / initialisation des variables de classe
  1998-10-07  7:30     ` Pierre Weis
@ 1998-10-07 13:03       ` Serge Fantino
  1998-10-07 21:25         ` Jerome Vouillon
  0 siblings, 1 reply; 10+ messages in thread
From: Serge Fantino @ 1998-10-07 13:03 UTC (permalink / raw)
  To: Pierre Weis; +Cc: caml-list, Vyskocil Vladimir

Bon. Je vais essayer de vous faire sentir ce qui me gene sur un exemple:

class test1 =
object
    val x = Random.int 1000
    method get = x
end

Je m'attends a ce que chaque nouvel objet cree a partir de test1 soit initialise
avec une valeur différente pour x.
En effet, l'initialisation est effectuee dans le corps de l'"object", elle ne
devrait donc etre effectuee que lorsque j'instancie un nouvel objet.
Or il n'en est rien:

List.map (fun _ -> (new test1)#get) [0;0;0;0;0;0]

retourne indifférement la meme valeur pour toutes les instances crees.
Par contre, si je declare la classe test2:

class test2 =
let random = Random.int 1000 in
object
    val x = random
    method get = x
end

alors effectivement, je m'attends au résultat obtenu.

 Ce n'est donc pas tand la porté des variables de classe qui me gene, mais le
deroulement de leur initialisation.
Tout ce qui est initialisé dans "object" devrait etre execute a chaque
instanciation, et non pas dépendre du "pattern" du constructeur.
(le fonctionnement de test1 et de test2 ne devrait pas etre equivalent...)

Ainsi, il n'y aurait pas de différence entre écrire "class test1 =" ou "class
test1 () =".
Par contre, il serait different d'ecrire "class test2 =" ou "class test2 () =", ce
qui est consistant avec le fonctionnement classique des fonctions en caml.
Actuellement, que ce passe-t-il ? Si je declare la classe test3:

class test3 range =
object
    val x = Random.int range
    method get = x
end

alors chaque nouvelle instance est initialisée avec une valeur différente de x, ie
l'initialisation est effectuée au moment de l'instanciation.

Si je declare maintenant:
class test3_1000 = test3 1000;;

il est logique de s'attendre a ce que test3_1000 soit une classe specialisée de
test3, fonctionnant de facon similaire a test3. Les expressions suivantes
devraient retourner des resultats similaires, ie des valeurs différentes <1000
pour chaque instance:
let l1 = List.map (fun _ -> (new test3 1000)#get) [0;0;0;0]
let l2 = List.map (fun _ -> (new test3_1000)#get) [0;0;0;0]

Helas, la liste l2 repete la meme valeur...  pourquoi ?

Une facon equivalente de declarer test3_1000 est la suivante:
class test3_1000 =
object
    inherit test3 1000
end

Je trouve l'ambiguite encore plus criante sous cette forme, et encore plus
incomprehensible !

On peut voir sans difficulte qu'un tel fonctionnement n'est absoluement pas
consistant avec les regles d'evaluation classique de caml. Soit la version
fonctionnelle de l'exemple précedent:

let test3_constructeur range = (* correspond a la declaration class test3 range =
*)
    let test3_object () = (* construction d'une instance *)
        let x = Random.int range in (* declaration du val x *)
            fun () -> x (* methode get *)
    in
        test3_object (* la classe definie le constructeur de la classe *)

Alors il est equivalent d'ecrire:
(new test3 1000)
et:
(test3_constructeur range) ()

la classe specialise devient:
let test3_1000_constructeur = test3_constructeur 1000

et les expressions suivantes donnent un resultat similaire :

let l1 = List.map (fun _ -> ((test3_constructeur 1000) ()) ()) [0;0;0;0]
let l2 = List.map (fun _ -> ((test3_constructeur_1000) ()) ()) [0;0;0;0]


Voila, j'espere avoir ete plus clair et plus convainquant.

Cordialement,

Serge Fantino


Pierre Weis wrote:

> > Sylvain BOULM'E wrote:
> >
> > > Bonjour,
> > >
> > > Il me semble que c'est dans la semantique des classes
> > > de Ocaml, qui supportent desormais les "variables statiques de classes"
> > > partagees par tous les objets de la classe. (Les gens de Ocaml me
> > > corrigeront ...)
> > >
> > > Ainsi,
> > >
> > > class test1 =
> > > object
> > >     val v = ref 5
> > >     method get = !v
> > >     method set x = v:=x
> > > end;;
> > >
> > > est equivalent a
> > >
> > > class test1 = let v1=ref 5 in
> > > object
> > >     val v=v1
> > >     ...
> > >
> > > Dans les 2 cas,
> > >
> > > let a=new test1 and b=new test1 in (b#set 4; a#get);;
> > >
> > > retourne 4.
> > >
> >
> > Effectivement, OCaml-2.0 semble fonctionné suivant ce schéma.
> > Je trouve cette "nouveauté" embarrassante:
>
> Je ne comprends pas le problème: cela ressemble fort à la sémantique
> habituelle du Caml de base...
>
> > - elle est ambigue;
>
> Je ne vois pas non plus en quoi elle l'est. Je ne connais pas grand
> chose aux objets mais ce comportement était celui que je prévoyais:
> la référence ref 5 est partagée dans les deux cas, comme dans le
> langage de base ...
>
> > Cela va a l'encontre du "sens commun". Les variables d'instance sont
> > declarees dans "object": je m'attends donc a ce que la porté de la variable
> > soit locale à une instance de la classe.
>
> C'est le cas. Je ne comprends pas. Ne confondez-vous pas partage des
> valeurs et portée des identificateurs ou variables ?
>
> > Lorsque je declare:
> >
> > class test1 =
> > object
> >     val v = ref 5
> >     method get = !v
> >     method set x = v:=x
> > end;;
> >
> > je m'attends a ce que la variable v soit locale à chaque nouvel objet
> > construit à partir de (new test1).
>
> C'est le cas. Seulement vous avez tout fait pour partager la référence
> ref 5: pas de paramètre à la classe donc calcul fait une fois pour
> toutes donc allocation unique donc partage. À quoi d'autre
> pourrions-nous nous attendre ?
>
> > D'ailleurs, il est confondant de voir que la déclaration suivante:
> >
> > class test3 =
> > object
> >     val mutable v = 5
> >     method get = v
> >     method set x = v<-x
> > end;;
> >
> > se comporte différement de test1 !
>
> Absolument pas. Il est rassurant que ça se comporte d'une façon
> différente, puisque maintenant la variable v est mutable!
>
> > - elle n'est pas consistante
> > Rien ne me previent du changement de fonctionnalité dans ce cas
> > particulier.
>
> Bien sûr que si: c'est cohérent car compatible avec toute la
> sémantique du langage de base (donc in fine avec celle de la réduction
> faible du lambda-calcul en appel par valeur). Enfin tout vous prévient
> de la différence entre les exemples: la présence du mot-clé mutable,
> l'absence de paramètre à la classe, le let ... in pour la deuxième
> version.
>
> > Il suffit de supprimer ou d'ajouter un paramètre à une classe pour en changer
> > complètement la sémantique.
> > Si je redefinis test1 :
> >
> > class test1 (x:int) =
> > object
> >     val v = ref x
> >     method get = !v
> >     method set x = v:=x
> > end;;
> >
> > alors la variable v n'est plus partagée...
>
> Bien entendu. Rien d'étonnant là-dedans. Avez-vous remarqué combien la
> sémantique d'une fonction change quand on modifie son nombre de
> paramètres ? En particulier lorsqu'une fonction passe de 1 à zéro
> paramètres comme c'est le cas ici ?
>
> Comparez par exemple:
>
> let f () = exit 0;;
>
> let f = exit 0;;
>
> Vous devriez observer une différence de sémantique certaine. Remplacez
> classe par fonction dans votre phrase et vous obtenez:
>
> ``Il suffit de supprimer ou d'ajouter un paramètre à une fonction pour
> en changer complètement la sémantique.''
>
> Il me semble que ce problème de paramètre ajouté ou suprimé est
> général à beaucoup de constructions du langage.
>
> Blague: disons-le en Caml !
>
> let étonnement = function construction ->
>   "Il suffit de supprimer ou d'ajouter un paramètre à " ^ construction ^
>   " pour en changer complètement la sémantique.";;
>
> étonnement "une classe";;
> étonnement "une fonction";;
> étonnement "un module";;
> étonnement "un foncteur";;
> étonnement "un type";;
>
> etc..
>
> > - elle n'est pas necessaire;
> > Si on en a besoin, on peut simplement partager des variables "statiques"
> > entre différentes instances de la meme classe.
>
> Je laisse la parole aux spécialistes des objets.
>
> > Enfin c'est mon avis d'utilisateur.
>
> Et il est très intéressant. Merci de nous le faire partager. Je crois
> qu'il montre aux implémenteurs de Caml qu'il y a sans doute un décifit
> d'explications sur le langage en général et sur ses objets en particulier.
>
> > Pour la petite histoire, il m'a fallu
> > tout un weekend pour comprendre pourquoi mon code ne marchait plus sous
> > OCaml-2.0, alors que la version 1.07 marche tres bien...
>
> Peut-être encore ce déficit d'explications ...
>
> > Objectivement votre,
> >
> >     Serge Fantino
>
> Cordialement,
>
> Pierre Weis
>
> INRIA, Projet Cristal, Pierre.Weis@inria.fr, http://cristal.inria.fr/~weis/







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

* Re: porte des definitions / initialisation des variables de classe
  1998-10-07 13:03       ` porte des definitions / initialisation " Serge Fantino
@ 1998-10-07 21:25         ` Jerome Vouillon
  1998-10-08 13:42           ` Serge Fantino
  0 siblings, 1 reply; 10+ messages in thread
From: Jerome Vouillon @ 1998-10-07 21:25 UTC (permalink / raw)
  To: Serge Fantino; +Cc: caml-list, Vyskocil Vladimir

On Wed, Oct 07, 1998 at 02:03:21PM +0100, Serge Fantino wrote:
> Bon. Je vais essayer de vous faire sentir ce qui me gene sur un exemple:
> 
> class test1 =
> object
>     val x = Random.int 1000
>     method get = x
> end
> 
> Je m'attends a ce que chaque nouvel objet cree a partir de test1 soit initialise
> avec une valeur différente pour x.
> En effet, l'initialisation est effectuee dans le corps de l'"object", elle ne
> devrait donc etre effectuee que lorsque j'instancie un nouvel objet.

Le contenu des enregistrements (dans le language de base) et des
structures (dans le langage de module) est évalué. Il me paraît donc
naturel que ce soit également le cas pour "object ... end" dans le
langage de classe.

> Actuellement, que ce passe-t-il ? Si je declare la classe test3:
>
> class test3 range =
> object
>     val x = Random.int range
>     method get = x
> end
>
> alors chaque nouvelle instance est initialisée avec une valeur
> différente de \ x, ie l'initialisation est effectuée au moment de
> l'instanciation.
>
> Si je declare maintenant:
> class test3_1000 = test3 1000;;
>
> il est logique de s'attendre a ce que test3_1000 soit une classe
> specialisée de test3, fonctionnant de facon similaire a test3. Les
> expressions suivantes devraient retourner des resultats similaires,
> ie des valeurs différentes <1000 pour chaque instance:
> let l1 = List.map (fun _ -> (new test3 1000)#get) [0;0;0;0]
> let l2 = List.map (fun _ -> (new test3_1000)#get) [0;0;0;0]
>
> Helas, la liste l2 repete la meme valeur...  pourquoi ?

Je ne comprends pas trop pourquoi ce résultat te choque. Les arguments
que tu donnes pourraient tout aussi bien s'appliquer à l'exemple
suivant :

type t = { x : int }
let test3 range = { x = Random.int range }
let test3_1000 = test3 1000
let l1 = List.map (fun _ -> (test3 1000).x) [0;0;0;0]
let l2 = List.map (fun _ -> (test3_1000).x) [0;0;0;0]

En fait, je crois que ce qui apparaît comme pas très intuitif est
que deux objets puissent partager une même valeur mutable. Mais c'est
également le cas lorsque l'on utilise Oo.copy ou {< ... >}.

-- Jérôme





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

* Re: porte des definitions des variables de classe
  1998-10-07 10:16     ` porte des definitions " Sylvain BOULM'E
@ 1998-10-08  7:33       ` Jacques GARRIGUE
  0 siblings, 0 replies; 10+ messages in thread
From: Jacques GARRIGUE @ 1998-10-08  7:33 UTC (permalink / raw)
  To: caml-list

From: "Sylvain BOULM'E" <Sylvain.Boulme@lip6.fr>

> Par contre, il est vrai que je trouve surprenant que :
> 
>   class test2 =
>     let v=ref 5
>     in fun () -> 
>           object 
>             method get = !v
>             method set x = v:= x
>          end;;
> 
>   let f=new test2 in 
>     let a=f() and b=f() in (b#set 4; a#get);;
> 
> retourne 5
> 
> au lieu de retourner 4, comme on s'y attenderait....

Ca m'a tout l'air d'un bug du compilateur.

    let a = new test2 () and b = new test2 () in (b#set 4; a#get);;

donne le meme resultat decevant, interdisant la creation de vraies
variables de classe.

	Jacques





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

* Re: porte des definitions / initialisation des variables de classe
  1998-10-07 21:25         ` Jerome Vouillon
@ 1998-10-08 13:42           ` Serge Fantino
  1998-10-09 13:12             ` Sylvain BOULM'E
  0 siblings, 1 reply; 10+ messages in thread
From: Serge Fantino @ 1998-10-08 13:42 UTC (permalink / raw)
  To: Jerome Vouillon; +Cc: caml-list, Vyskocil Vladimir

Jerome Vouillon wrote:

> On Wed, Oct 07, 1998 at 02:03:21PM +0100, Serge Fantino wrote:
> > Bon. Je vais essayer de vous faire sentir ce qui me gene sur un exemple:
> >
> > class test1 =
> > object
> >     val x = Random.int 1000
> >     method get = x
> > end
> >
> > Je m'attends a ce que chaque nouvel objet cree a partir de test1 soit initialise
> > avec une valeur différente pour x.
> > En effet, l'initialisation est effectuee dans le corps de l'"object", elle ne
> > devrait donc etre effectuee que lorsque j'instancie un nouvel objet.
>
> Le contenu des enregistrements (dans le language de base) et des
> structures (dans le langage de module) est évalué. Il me paraît donc
> naturel que ce soit également le cas pour "object ... end" dans le
> langage de classe.
>

Ce qui est naturel, c'est que l'objet soit initialisé lorsqu'il est créé. Or l'objet
est créé lorsqu'on appelle "new", pas lorsque l'on définit la classe...

Que ce passe-t-il dans caml ? (j'espere que vous me corrigerez...)
- "class xxx" définit la classe "xxx", qui n'est pas une valeur caml standard (elle
vit dans l'espace des classes, avec un espace de nom séparé,...)
- "class xxx" définit également un constructeur, qui est une fonction caml standard à
valeur "object"
- "new" est une fonction spéciale, définie de l'espace des classes dans l'espace des
valeurs standards: elle associe à un nom de classe son constructeur, permettant
d'instancier un nouvel objet

Le fonctionnement normal d'un objet est donc le suivant:
    * les objets sont initialisés à chaque appel à "new"
    * les valeurs des variables d'instances sont a priori indépendantes (sauf si
explicitement lors de l'instanciation JE décide de partager une valeur entre certains
objets, OU si je définis le constructeur de classe de tel sorte qu'il définisse un
environnement commun à tous les objets)

Maintenant, examinons le cas où la classe est définie "sans paramètre":
- le constructeur n'est pas une fonction à valeur "object" mais simplement une
constante "object": l'objet est instancié lors de la définition de la classe
- la fonction spéciale "new" retourne une copie de l'objet constant, ce qui a comme
conséquences:
    * tous les objets de la classe sont initialisés avec les memes valeurs
    * toutes les valeurs "pointeurs" (array,hashtbl,ref,...) sont partagées par tous
les objets de la classe (par contre les variables déclarées "mutable" sont
indépendantes (?))

Est-ce que c'est correct ?

Si oui,  il me semble alors que la sémantique du langage est uniquement conditionnée
par l'implémentation.
Je ne vois aucune raison a priori pour que le mécanisme d'instanciation soit
différent selon que la classe accepte ou non des paramètres. De plus je trouve
anormal que la définition d'une classe puisse induire l'instanciation d'un objet:
classes et objets "vivent" dans des espaces différents; seule la fonction spéciale
"new" devrait permettre de passer de l'un à l'autre.

Pour moi, l'implémentation de caml devrait vérifier:
"les variables d'instances sont initialisées à chaque création d'un nouvel objet".

 Cela dit, je peux complètement me tromper, ne pas voir l'évidence, etre le seul à
trouver le fonctionnement actuel "counter-intuitive".

Cordialement,

Serge Fantino

PS: En OCaml-1.0x, la définition d'une classe sans paramètre était prohibée, ainsi
que l'évaluation partielle des constructeurs:  la raison de ce bridage (volontaire ?)
n'était-elle pas d'éviter ce genre de problème ?


> > Actuellement, que ce passe-t-il ? Si je declare la classe test3:
> >
> > class test3 range =
> > object
> >     val x = Random.int range
> >     method get = x
> > end
> >
> > alors chaque nouvelle instance est initialisée avec une valeur
> > différente de \ x, ie l'initialisation est effectuée au moment de
> > l'instanciation.
> >
> > Si je declare maintenant:
> > class test3_1000 = test3 1000;;
> >
> > il est logique de s'attendre a ce que test3_1000 soit une classe
> > specialisée de test3, fonctionnant de facon similaire a test3. Les
> > expressions suivantes devraient retourner des resultats similaires,
> > ie des valeurs différentes <1000 pour chaque instance:
> > let l1 = List.map (fun _ -> (new test3 1000)#get) [0;0;0;0]
> > let l2 = List.map (fun _ -> (new test3_1000)#get) [0;0;0;0]
> >
> > Helas, la liste l2 repete la meme valeur...  pourquoi ?
>
> Je ne comprends pas trop pourquoi ce résultat te choque. Les arguments
> que tu donnes pourraient tout aussi bien s'appliquer à l'exemple
> suivant :
>
> type t = { x : int }
> let test3 range = { x = Random.int range }
> let test3_1000 = test3 1000
> let l1 = List.map (fun _ -> (test3 1000).x) [0;0;0;0]
> let l2 = List.map (fun _ -> (test3_1000).x) [0;0;0;0]
>
> En fait, je crois que ce qui apparaît comme pas très intuitif est
> que deux objets puissent partager une même valeur mutable. Mais c'est
> également le cas lorsque l'on utilise Oo.copy ou {< ... >}.
>
> -- Jérôme





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

* Re: porte des definitions / initialisation des variables de classe
  1998-10-08 13:42           ` Serge Fantino
@ 1998-10-09 13:12             ` Sylvain BOULM'E
  0 siblings, 0 replies; 10+ messages in thread
From: Sylvain BOULM'E @ 1998-10-09 13:12 UTC (permalink / raw)
  To: Serge Fantino; +Cc: Jerome Vouillon, Vyskocil Vladimir, caml-list


Bonjour,

> Pour moi, l'implémentation de caml devrait vérifier:
> "les variables d'instances sont initialisées à chaque création d'un nouvel objet".
> Cela dit, je peux complètement me tromper, ne pas voir l'évidence, etre le seul à
> trouver le fonctionnement actuel "counter-intuitive".

Le probleme que tu enonces releve d'un choix. Le tien a l'avantage
d'etre plus simple. Celui des developpeurs de Ocaml, qui est celui
de l'evaluation "lazy" (on evalue le plus tot possible), a l'avantage
d'etre plus efficace (on evalue qu'une fois des expressions, qui dans ton
choix sont evaluees plusieurs fois) tout en etant plus general (car on 
peut quand meme ecrire facilement les programmes que tu as envie d'ecrire). 

De mon point de vue, la difference de comportement (d'un point de vue 
semantique)
entre les deux intervient lorsqu'on programme avec "effets de bord". Et dans 
ce cas,
il faut de toute facon mieux s'interroger plusieurs fois sur la maniere dont 
les expressions
sont evaluees. La solution de Ocaml me convient donc totalement...

Cordialement,

Sylvain.





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

end of thread, other threads:[~1998-10-09 15:29 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1998-10-05 15:10 porté des définitions des variables de classe Serge Fantino
1998-10-06 12:35 ` port des d finitions " Sylvain BOULM'E
1998-10-06 16:12   ` porte des definitions " Serge Fantino
1998-10-07  7:30     ` Pierre Weis
1998-10-07 13:03       ` porte des definitions / initialisation " Serge Fantino
1998-10-07 21:25         ` Jerome Vouillon
1998-10-08 13:42           ` Serge Fantino
1998-10-09 13:12             ` Sylvain BOULM'E
1998-10-07 10:16     ` porte des definitions " Sylvain BOULM'E
1998-10-08  7:33       ` Jacques GARRIGUE

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).