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.

Author: jf

Created: 2023-11-02 jeu. 18:25

Validate