Remarques diverses (style, etc.) – PF, Info4
Table of Contents
Ce document contient des éclaircissements sur certaines questions issues des retours des élèves en TD ou TP. Il sera complété en fonction des demandes de précisions à venir.
1 Écritures équivalentes pour définir une fonction typée
Pour définir une fonction prenant x
de type type_de_x
puis y
de type type_de_y
et rendant un résultat (défini par code
)
de type typ_resultat
, nous avons utilisé
let ma_fonction : type_de_x -> type_de_y -> type_resultat = fun x -> y -> code
On obtient exactement la même chose en écrivant :
let ma_fonction (x : type_de_x) (y : type_de_y) : type_resultat = code
Cela reste valable pour les fonctions récursives, avec
let rec
au lieu de let
.
2 Définitions locales à l'intérieur d'une définition globale
2.1 Rappel du principe
Vous connaissez déjà le let in
pour des données, par exemple :
let valeur1 : type1 = let valeur_aux1 = code_aux1 in let valeur_aux2 = code_aux2 in fonction valeur_aux1 valeur_aux2
On aurait pu écrire aussi :
let valeur_aux1 = code_aux1 let valeur_aux2 = code_aux2 let valeur1 : type1 = fonction valeur_aux1 valeur_aux2
Mais l'inconvénient est que cela expose publiquement valeur_aux1
et valeur_aux2
. Et par exemple si on veut définir une seconde valeur
sur le même schéma, mais avec des codes différents,
il est bien plus propre d'écrire
let valeur1 : type1 = let valeur_aux1 = code_aux1 in let valeur_aux2 = code_aux2 in fonction valeur_aux1 valeur_aux2 let valeur2 : type1 = let valeur_aux1 = autre_code_aux1 in let valeur_aux2 = autre_code_aux2 in fonction valeur_aux1 valeur_aux2
que
let valeur_aux1 = code_aux1 let valeur_aux2 = code_aux2 let valeur1 : type1 = fonction valeur_aux1 valeur_aux2 let valeur_aux1 = autre_code_aux1 let valeur_aux2 = autre_code_aux2 let valeur2 : type1 = fonction valeur_aux1 valeur_aux2
Cela reste valable lorsque valeur_aux1
, valeur_aux2
représentent des fonctions auxiliaires (éventuellement récursives).
Cela est notamment mis en application dans les programmes d'analyse syntaxique.
2.2 Utilisation dans les analyseurs fournis en exemple
Au début de analist_exemples.ml
et de anacomb_decouverte.ml
se trouve la fonction list_of_string
destinée à faciliter les tests.
let list_of_string s = let n = String.length s in let rec boucle i = if i = n then [] else s.[i] :: boucle (i+1) in boucle 0
Ici la fonction récursive boucle
est définie
de façon interne, et l'identificateur boucle
pourra être réutilisé ailleurs sans conflit possible.
Autre exemple, dans sommechiffres_corr.ml
.
Plusieurs analyseurs sont rédigés sur un modèle commun,
comportant une fonction pour l'analyse d'un seul terminal,
une fonction pour l'analyse d'au moins un terminal,
une fonction pour l'analyse de zéro (aucun) terminal.
Ces fonctions sont nommées un_quelquechose
(qui lui
est en général unique et est parfois utilement mis à l'extérieur),
puis surtout au_moins_un
et aucun
.
Il est donc préférable d'en faire des fonctions locales ainsi :
let rec chiffres : analist = let un_chiffre : analist = terminal_cond est_chiffre in let au_moins_un : analist = fun l -> let l = un_chiffre l in let l = chiffres l in l and aucun : analist = epsilon in fun l -> try au_moins_un l with Echec -> aucun l
Dans ce même fichier sommechiffres_corr.ml
, vous
avez la variante de chiffres
nommée sommechiffres
qui est fabriquée sur ce même modèle.
let rec sommechiffres : int ranalist = let rec au_moins_un : int ranalist = fun l -> let x, l = un_chiffre l in let n, l = sommechiffres l in x + n, l and aucun : int ranalist = epsilon_res 0 in fun l -> try au_moins_un l with Echec -> aucun l
Même horner
, la question suivante, respecte ce modèle.
Sur le même modèle on peut aussi définir une fonction qui analyse
cette fois des suites de caractères alphabétiques.
Ce n'est pas fait dans les fichiers donnés, mais c'est utile
dans l'exercice Connect6
, du moins
si vous restez sur des définitions dans ce style.
C'est moins utile si vous passez à la version avec combinateurs car le code devient naturellement si concis que l'on ne sent plus le besoin d'employer des définitions auxilaires locales.