Pour préciser ce qu’a dit Aabu : bien sûr, quand ton programme OCaml où tu as écrit let a = 2
est exécuté, ton a
est stocké en mémoire. Et bien sûr, ton ordinateur a la capacité technique de modifier le contenu de cette case mémoire, puisqu’il est câblé pour ça.
Mais même s’il est possible pour ton ordinateur de le faire, OCaml ne te fournit pas de moyen d’écrire cette modification (sauf si tu passes par exemple par une référence explicite).
L’intérêt, c’est que puisque tu n’as pas pu écrire de modification de cette variable, OCaml est sûr que ce a
là désigne toujours la même valeur. C’est utile pour toi, parce que tu évites les comportements problématiques et difficiles à débuguer où une variable que tu utilises dans une fonction est modifiée quelque part dans un autre fichier sans que tu t’en soies rendu compte. C’est en général ce que les gens considèrent comme une des forces de la programmation fonctionnelle. C’est aussi utile pour ton compilateur, parce que le fait que cette variable ne soit pas modifiée peut lui permettre de faire tout un tas d’optimisations qui seraient impossibles dans le cas contraire.
Edit : puisque tu as répondu entre temps :
let a = 0 in
n’est pas une expression tout seul. Par contre, let a = 0 in a + 2
est une expression de type int
dont la valeur est 2
. En OCaml, tu n’as pas à te préoccuper de l’allocation : ce n’est pas quelque chose que tu peux observer. On peut dire que le langage abstrait la gestion de la mémoire pour te permettre de te concentrer sur le reste. D’ailleurs, en l’occurrence, il est bien possible que le compilateur décide de ne pas allouer et de tout simplement remplacer cette expression par 2
, puisqu’elle est constante.
Pour ta deuxième question, attention, tu peux écrire let a = 0 in a = 1
, mais ça n’a pas le sens que tu sous-entends dans ton message : ici, le deuxième =
est l’égalité des valeurs (le ==
d’autres langages, en quelque sorte). =
a deux sens différents : s’il est combiné avec un let
(ou d’autres constructions semblables), il sert à définir quelque chose, et s’il est utilisé comme un opérateur (ici, c’est le a = 1
, on aurait pu aussi utiliser l’opérateur +
et écrire let a = 0 in a + 1
), c’est le test d’égalité. let a = 0 in a = 1
est donc une expression de type bool
et de valeur false
. Note qu’OCaml a aussi un opérateur ==
qui teste autre chose et que tu ne devrais pas utiliser pour l’instant (c’est d’ailleurs assez rare d’en avoir besoin).
Je crois avoir répondu plus haut à « pourquoi on ne peut pas écrire ça ». Note que tu peux écrire quelque chose comme :
| let a = 0 in
let a = 1 in
a + 2
|
Cette expression vaut 3
. On serait tenté de croire que le deuxième let
modifie la valeur de a
, mais ce n’est pas le cas : il définit une nouvelle variable a
qui vaut 1
. Comme elle a le même nom que la précédente, elle la masque simplement, elle ne modifie pas sa valeur. On peut le voir sur le code suivant :
| let a = 0 in
(let a = 1 in a + 2),
a + 4
|
La construction a, b
sert à construire un couple de valeurs. Ici, j’ai entouré le let a = 1
de parenthèses pour limiter sa portée : ainsi, le a + 2
vaudra 3
(puisque le a = 1
a masqué la définition du a = 0
). Par contre, une fois sorti de ces parenthèses, le a + 4
vaut 4
: la valeur du a
défini par le let a = 0
n’a pas été modifié, et son nom n’est plus masqué ici. Tout cette expression a donc la valeur (3, 4)
.
Pour le ()
, tu peux le voir comme une astuce qui permet de mélanger facilement expressions et instructions : en simplifiant, tu peux simplement voir les instructions comme des expressions de type unit
(dans lequel il n’y a qu’une valeur, ()
). Ça permet d’utiliser des instructions partout où on peut utiliser une expression. Je pense qu’il ne faut pas te prendre la tête dessus pour l’instant et simplement pratiquer un peu, et c’est quelque chose qui te paraîtra finalement plutôt naturel une fois que tu auras compris comment ça fonctionne.