Dans l'exerice précédent, que se passerait-il si on modifiait directement la chaîne entree
, c'est-à-dire si on n'en faisait pas une copie pour faire les modifications ?
let inverse_chaine_bis chaine = for i = 0 to pred (taille / 2) do let temp = chaine.[i] in chaine.[i] <- chaine.[taille - 1 - i]; chaine.[taille - 1 - i] <- temp; done; chaine in let s = "un test" in let t = inverse_chaine_bis s in print_string t;
La valeur retourne un résultat correct, mais la chaîne qui est retourné est la même que celle qui a été donné en paramètre. C'est-à-dire que s
et t
sont les mêmes chaînes. Pour s'en rendre compte, rajoutez le code suivant, qui affiche s
, et qui regarde si une modification sur t
modifie également s
.
print_string s; t.[0] <- 'r'; print_string s;
affiche "tset nu"
puis "rset nu"
.
En fait, la fonction inverse_chaine_bis
n'a pas besoin de retourner une chaîne. Écrivons la fonction inverse_chaine_ter
, de type string -> unit
, qui prend une chaîne en paramètre et qui remplace cette chaîne par son symétrique :
let inverse_chaine_ter chaine = for i = 0 to pred (taille / 2) do let temp = chaine.[i] in chaine.[i] <- chaine.[taille - 1 - i]; chaine.[taille - 1 - i] <- temp; done; in let s = "un test" in inverse_chaine_ter s; print_string s;
Vocabulaire : on dit que la fonction inverse_chaine_ter
modifie chaine
en place.
Il est important de bien saisir la différence :
- la fonction
inverse_chaine
ne modifie pas son argument, et renvoie une autre chaîne contenant le résultat, - la fonction
inverse_chaine_ter
modifie son argument et ne renvoie rien.
Ces deux fonctions sont donc conceptuellement différentes, même si on utilise l'une où l'autre pour faire la même tâche, qui est de retourner une chaîne. Y a-t-il une fonction mieux que l'autre ? Non, cela dépend entièrement de ce que l'on veut en faire. On reviendra sur cette question.