Open jpages opened 10 years ago
Salut Julien.
J'aurais tendance à dire qu'il s'agit plus d'un type final fixé selon ta définition.
Par contre. Ce type n'est pas tant "fixé" car il est possible de le redéfinir de manière covariante dans les sous classes.
class A
type FOO: Object
end
class B super A
redef type FOO: Int
end
Le 3 mars 2014 04:11, "jpages" notifications@github.com a écrit :
Avec la portion de code suivante :
class A type T : Truc
fun newInstance : T do var truc = new Truc return truc endend
On définit une classe A avec un type virtuel borné par Truc. Dans la méthode newInstance on veut retourner une instance de T.
La borne du type virtuel nous dit que T <: Truc, mais pas que Truc <: T (enfin je crois).
Est-ce que c'est normal ? Et est-ce qu'il faut comprendre T : Truc comme une borne ou alors comme T = Truc (type final fixé). Si c'est une borne, alors dans mon exemple, newInstance devrait lever une erreur et sinon ça me paraît normal.
Reply to this email directly or view it on GitHubhttps://github.com/privat/nit/issues/298 .
« Est-ce c'est normal ? » Ca dépend de ta définition de normal :)
Dans le système de type de Nit, Truc
n'est pas sous-type de T
. C'est le comportement normalement attendu pour qui suit des cours de prog objet avancée, car non sur (cf le cas de la redéfinition de T
).
Notons que si T
était fixé ; T
et Truc
deviennent équivalents; donc trivialement sous-type.
Maintenant, pourquoi ce comportement ? Plusieurs raisons dont principalement flemme, compatibilité avec du vieux code et prévision du futur.
En fait, nitg sait que c'est pas sous-type. mais le laisse passer explicitement : cf check_subtype
dans typing.nit. le commentaire indique workarround to the current unsafe typing policy. To remove once fixed virtual types exists.
Ensuite, les moteurs savent que certains trucs sont pas sur et ajoutent un cast explicite dans ces cas là. Ils l'appellent autocast dans la terminologie des moteurs.
Le comportement est vérifié dans tests/base_autocast.nit
L'option --no-check-autocast
désactive ces tests (pour mesurer leur cout par exemple)
L'option --typing-test-metrics
permet aussi de les compter (statiquement et dynamiquement, c'est la ligne auto
) ; dans nitg il y a actuelle 27 autocast dans le code (0.5%), mais ils comptent pour un total de 27M cast au runtime (3.6%). j'imagine que la plupart sont en fait dans kernel.nit
Ainsi, au final dans ton exemple original, Nit rajoute un cast implicite, donc d'une certaine façon c'est traité comme une sorte de covariance non sure :
class A
type T : Truc
fun newInstance : T
do
var truc = (new Truc).as(T) # ajout cast implicite
return truc
end
end
Et pour le futur ? Ben, ces cast implicites sont nul et on devrait plutot lever une erreur statique pour que le programmeur prennent la responsabilité (et 27 cas dans nitg n'est pas impressionnant non plus, donc on peut pas vraiment parler d'une augmentation monstruseuse de verbosité)
Malheureusement ces 27 cas sont sans doute des cas légitime de types virtuels fixés qui n'attendent que ça pour devenit légaux. Ce serait idiot de mettre 27 cast explicites pour les virer a nouveau une fois que le fixage des types virtuels est en place.
Donc, comme plusieurs trucs de Nit, le machin est dans un état ni-fait-ni-a-faire et plutôt que d'ajouter un pansement, on attend qu'un volontaire ajoute le fixage des types virtuels une bonne fois pour toute.
En fait dans l'example de Jean, le cast est fait sur le return et non le new:
class A
type T : Truc
fun newInstance : T do
var truc = new Truc
return truc.as(T) # ajout cast implicite
end
end
Ok d'accord je comprends.
J'essayerai de regarder à l'occasion voir si c'est pas trop compliqué à implémenter.
Après analyse et discussion il semblerait qu'il n'y ait pas de solution magique d'éviter un cast, même avec les types virtuels fixés.
Je vais faire des analyses pour compter les cas d'autocasts
et il faudra décider si on garde les auto-casts implicite ou si on dois les rendre explicites.
Avec la portion de code suivante :
On définit une classe A avec un type virtuel borné par Truc. Dans la méthode newInstance on veut retourner une instance de T.
La borne du type virtuel nous dit que T <: Truc, mais pas que Truc <: T (enfin je crois).
Est-ce que c'est normal ? Et est-ce qu'il faut comprendre T : Truc comme une borne ou alors comme T = Truc (type final fixé). Si c'est une borne, alors dans mon exemple, newInstance devrait lever une erreur et sinon ça me paraît normal.