L'Inférence de type
L'inférence de type fait référence au fait que l'information sur le type n'est pas vérifiée uniquement pendant l'exécution du programme. Elle l'est aussi pendant la rédaction. Le typage n'a pas besoin d'être résolu immédiatement. Par exemple une variable locale peut être déclarée sans type (elle sera du type Unknown). Elle sera typée lors de sa première utilisation et prendra le type de la valeur requise dans l'expression.
Affichage du type
Il est possible d'utiliser l'instruction type pour connaitre le type d'une expression passée en paramètre. Cependant, lors de la compilation l'instruction type sera ignorée et seul l'expression passée en paramètre sera évaluée :
var x : Int = type(0);
L'exemple précédent affichera Int à la compilation mais produira le même code que si type n'avait pas été utilisée.
Cette particularité peut être pratique pour connaitre un type sans avoir à entrer dans le code d'une classe ou lire la documentation.
Inférence des variables locales
L'inférence de type est capable de typer strictement le programme dans sa totalité, sans pour autant à avoir à spécifier un seul type lors de la rédaction. En particulier, les variables locales n'ont pas besoin d'être typées. Elles le seront lors de leur premier accès en lecture ou en écriture:
var loc; type(loc); //--> Unknown<0> loc = "hello"; type(loc); //--> String
Inférence de type des fonctions
Déclarer le type des paramètres d'une fonction n'est pas obligatoire non plus. Le type des paramètres sera fixé lors du premier appel à la fonction suivant les valeurs passées. Il faut donc faire très attention à l'ordre d'exécution du programme. En voici un exemple :
function f( posx ) { // .... } // ... f(134); f(12.2); //--> Erreur: la fonction attend un Int (Error : Float should be Int)
Le premier appel à f définie le type de 'posx en tant que Int. Le second appel induit une erreur de compilation car f attend maintenant un Int et non un Float. En inversant les deux appels à f, 'posx est défini comme un Float en premier. Lors du second appel, Int étant un type héritant de Float, la compilation ne pose aucun problème.
function f( posx ) { // .... } // ... f(12.2); // défini le paramètre comme un Float f(134); // Succès !
Dans l'exemple précédent, les deux appels à la fonction sont proches, déboguer en cas de problème est donc aisé. On comprendra, par contre, que dans le cas d'un programme plus conséquent, fixer l'erreur demandera beaucoup plus de travail. La solution la plus simple est de spécifier le type des paramètres des fonctions. Les erreurs éventuelles seront ciblées en retour de compilation.
Le premier exemple est réécrit comme suit :
function f( posx : Int ) { // .... } // ... f(134); f(12.2); // Le compilateur pointera cette ligne !
Choix de l'utilisateur
L'utilisation de l'inférence de type est en fait un choix du programmeur. Il est possible de laisser le travail d'inférence des types au compilateur ou de tous spécifier lors de la rédaction pour garder un contrôle total. Le mieux serait un compromis en spécifiant certains types pour améliorer la documentation et laisser le reste du travail au compilateur pour une rédaction plus rapide.
Dans tous les cas, outre l'utilisation de Dynamics (voir le chapitre dédié), le programme sera strictement typé et tout usage illicite sera détecté à la compilation.