* 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 / 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 / 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
* 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 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
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