Enregistrements, puis objets
|
|
|
Noté
|
En mathématiques deux outils,
Et en informatique…
Une position sur la terre est une paire latitude × longitude.
Une erreur idiote : let x = (2.208, 47.800)
au lieu de let x = (47.800, 2.208)
.
Un enregistrement est d’abord un n-uplet dont les composantes sont nommées,
Le programmeur n’a plus besoin de se souvenir que la latitude vient en premier, il peut écrire :
Cela évite bien des erreurs idiotes et conduit à des programmes plus clairs :
x.latitude
au lieu de fst x
.
Dans les languages usuels, les enregistrements expriment le produit (cartésien) de façon commode.
(47.800,2.208)
.x.latitude
, le compilateur comprend
fst x
.
Ajoutons les altitudes aux positions sur la terre.
Monter d’un mètre :
C’est assez lourd, on peut abréger en :
Une sorte supplémentaire : les étiquettes (comme des variables, mais ne sont jamais liées).
Des symboles supplémentaires qui fabriquent des termes.
{ ℓ1=t1 ; ⋯ ℓn=tn; }
t.ℓ
.
{ t1 With ℓ=t2 }
.
Définition de l’AST de PCF en Caml.
Syntaxe concrète :
Syntaxe abstraite :
Et une nouvelle règle d’interprétation.
|
Donc une nouvelle valeur (notée { ℓ1 = v1 ; ⋯ ℓn = vn; }).
Note : Dans un contexte typé (simple), la valeur d’un enregistrement serait un n-uplet.
La taille n et la position des champs sont définis à partir d’une déclaration de type enregistrement.
Syntaxe concrète
Syntaxe abstraite :
|
Syntaxe concrète
Syntaxe abstraite :
|
|
Sur le transparent précédent nous avons « défini »
|
« Sucre syntaxique » veut dire qu’il n’y pas de nœud correspondant à la construction définie dans l’AST de PCF.
La nouvelle construction existe slt. dans la syntaxe concrète.
Par abus de langage, on peut considérer un AST généralisé.
Et que la sémantique de la nouvelle construction se déduit facilement (ici la nouvelle règle est lourde).
En PCF le code suivant est pour le moment interdit :
Pourquoi ? À cause de la sémantique de CopyWith, (justifiée par l’implémentation efficace dans le cas typé.)
Mais, pour PCF non-typé, on ajoute facilement la règle :
|
Avec la notation L({ ℓ1 = v1 ; ⋯ ℓn = vn; }) = { ℓ1, … , ℓn }.
Dans le cadre non-typé, l’accès t.ℓ
réussit dès que
t s’évalue en un enregistrement qui possède le champ ℓ.
|
Comment transporter cette bonne propriétée à PCF typé :
Il faut une forme de sous-typage.
Genre getx
prend un p
qui comprend au moins le champ x
(type pos
= {x:float;...}
) et
pos2
et pos3
sont des sous-type pos
.
4.x
.
{ {x=1} With y=2 }
.
t1 sous-type de t2 veut dire essentiellement que t1 a plus de champs que t2.
Le principe général est d’évaluer aussi tard que possible.
Les règles sont donc logiquement.
|
|
Il y a peu à dire en fait.
(fact 10
évalué deux fois en appel par nom.)
Une petite entreprise X
.
D’une part un salarié à payer.
D’autre part des commandes.
Éditer des fiches de paie/des bons de commande
imprimer_fiche
, imprimer_bon
, etc.
imprimer
» qui sait imprimer
une repectivement une fiche de paie et un bon de commande.
Rien n’empêche d’ajouter un champ « imprimer
»,
à la fois aux salariés et aux commandes :
Et pour imprimer que x soit un salarié ou une commande :
Faire avancer un animal :
Et on a (avec un toplevel approprié).
PCF> go lapin;; - = { x=5 ; step=<fun> } PCF> go tortue;; - = { x=1 ; step=<fun> } PCF> go (go lapin) ;; - = { x=10 ; step=<fun> }
Objet : enregistrement dont tous les champs sont des méthodes.
Méthode :
o.m o a1 ⋯ an |
Notre tortue n’est pas encore tout à fait un objet :
Mais elle possède bien une méthode step.
Créer un objet :
Obj x -> { ℓ1 = t1 ; ⋯ ℓn = tn; } ∼ { ℓ1 = Fun x -> t1 ; ⋯ ℓn = Fun x -> tn; } |
On peut voir Obj comme « sucre syntaxique » (i.e. existe slt dans la syntaxe concrète).
Ou comme nouvelle construction de la syntaxe abstraite, dont la sémantique est :
|
Invoquer une méthode :
t#ℓ ∼ Let o = t In o.ℓ o |
Éventuellement, sémantique :
|
Redéfinition (Ajout) de méthode
Obj x -> {t1 With ℓ = t2} ∼ {t1 With ℓ = Fun x -> t2} |
Éventuellement, sémantique (assez évidente).
|
|
Supprimer les constructions des enregistrements de la syntaxe (mais conserver les enregistrements dans la sémantique).
Mais alors comment écrire la tortue « objet ». Facile ?
Qui veut dire :
On note que dans un language comme Java, self
est implicite
et s’appelle this.
PCF> let t = tortue#step;; val t = { x=<fun> ; step=<fun> } PCF> t#x;; - = 1
Qui s’explique, puisque t
est
{ x= <s•self#x+1•E> ; ⋯ } |
Où E = [ self = { x=<self•0•E0> ; ⋯} ; …]
Ou si on préfère : t#x
est « Fun s -> self#x+1 » pris dans un environnement où
self est un objet dont la méthode x vaut Fun _ -> 0
Et, miracle, tt
= t#step
vaut bien 2.
Car tt#x
est « Fun s -> self#x+1 » pris dans un environnement où self vaut t
(et donc self#x
renvoie 1).
Est quand même un peu trop radical, il devient plus raisonable si on considère des constructions impératives :
(Possible car la variable x
et la méthode x
habitent deux
espaces de noms différents).
Mais en fait, sans champs mutable cela reste assez bizarre.
Nous en restons là, car PCF objet est quand même exemplaire de la programmation objet.
Comparer
Résultat : 10 (liaison statique). Et
Résultat : 11 (liason tardive de self).
En fait la méthode a n’a pas besoin d’exister quand on définit f.
Évidemment, dans un contexte typé, il faudra sans doute déclarer a.
En Java les objets ne sont pas définis directement mais en instanciant des classes, par ex.
Et par exemple :
L’ajout/redéfinition de méthode opère donc plus sur les classes que sur les objets.
Un objet de la classe Animal
est représenté en machine
disons comme une paire :
int
).
getx
et la seconde step
).
Il y a une table des champs par objet et une table des méthodes par classe.
go
n’a pas besoin de savoir si
a
est une Tortue
ou un Lapin
, il lui suffit
de savoir que step
est en seconde position.
La methode step
est une fonction qui prend un premier argument
implicite (paramètre formel this
),
qui vaut a
dans l’invocation a.step()
.
En java on peut écrire :
Et on obtient une tortue deux fois plus rapide.
En PCF objet c’est nettement plus tordu :
On peut donc conjecturer qu’en Java
super.step
appelle la méthode step
de la classe parent
sur… this
.
Nous avons laissé de côté bien des sujets :
⋮ |
Ce document a été traduit de LATEX par HEVEA