Une fonction est annotée avec le mot-clé `fn` suivi de son identifiant.
Son type de retour se trouve à droite après la *flèche* (en ASCII-art) `->`.
Si une fonction n'a pas de type de retour explicite (il n'y a pas de flèche) le type de retour est `()` qui
rappelle le type `void` de C (aka sans type, mais oui c'est un type en Rust). Entre parenthèses se trouvent les arguments de la fonction suivi de leur type. Le nombre d'arguments est supérieur ou égal à zéro.
Une fonction est ensuite appelée par son identifiant et ses éventuels arguments.
La fonction `read_command_line()` ne prend ainsi aucun argument et retourne un tableau statique d'entier 32 bits et de taille `SIZE`.
Pour qu'une fonction retourne une valeur, on a deux solutions:
1. Si la valeur est la dernière expression de la fonction, on peut juste mettre la valeur (ou la variable) sans point virgule à la fin de la ligne.
2. On peut, de façon similaire au C, utiliser le mot clé `return val;`
On constate ici que les tableaux statiques (contrairement à ce qui se passe dans le langage C) peuvent être retournés
par une fonction (le tableau n'est pas désalloué au moment du retour).
La vérification de la taille du tableau se fait dans la fonction `check_size(size: usize)` qui prend donc un argument de
type `usize` et ne retourne rien.
```rust,should_panic
fncheck_size(size:usize){
# if size == 0 {
# panic!("Size is of tab = 0.");
# }
}
# fn main() {
check_size(10);// runs alright
check_size(0);// panics
# }
```
À l'inverse la fonction `print_tab(tab)` prend en argument un tableau statique et ne retourne rien.
```rust
# const SIZE: usize = 9;
# fn read_command_line() -> [i32; SIZE] {
# [10, 32, 12, 43, 52, 53, 83, 2, 9]
# }
fnprint_tab(tab:[i32;SIZE]){
fortintab{
print!("{} ",t);
}
println!();
}
# fn main() {
lettab=read_command_line();
print_tab(tab);
# }
```
Les fonctions `min_i32(lhs, rhs)` retourne la plus petite valeur de deux entiers signés de 32 bits.
```rust
fnmin_i32(lhs:i32,rhs:i32)->i32{
iflhs<rhs{
lhs
}else{
rhs
}
}
# fn main() {
letmin=min_i32(2,10);
println!("{min}");
#}
```
### En Rust le `if` est une expression
Mais si vous étudiez attentivement ce code, on constate que le corps de la fonction est étrange.
On voit qu'aucune ligne ne possède de point terminal. Cela voudrait dire que `lhs` ou `rhs` sont la dernière expression
de la fonction. En fait ce qui se passe c'est que le `if ... else` est une **expression**. De façon similaire au
`if` ternaire en `C`, le `if ... else` en Rust retourne une valeur. On peut écrire de façon équivalente au code ci-dessus
```rust
fnmin_i32(lhs:i32,rhs:i32)->i32{
letmin=iflhs<rhs{
lhs
}else{
rhs
};
min
}
# fn main() {
letmin=min_i32(2,10);
println!("{min}");
#}
```
On voit qu'ici à la fin du bloc du `else` nous avons un point virgule qui indique la fin de la ligne.
Ainsi `lhs` ou `rhs` sont liés à la variable immutable `min`.
Cette notion d'expression est très importante. Comme nous l'avons expliqué précédemment la dernière expression d'une fonction est évaluée puis retournée par cette dernière.
Un bloc de code qui produit un résultat est une expression.
En Rust, plusieurs structures de contrôle tel que le `If` sont des expression. Il n'est pas nécessaire de connaître la valeur de l'expression pour la retourner.
Nous pourrions considérer par exemple les fonctions suivante :
```rust,no_run
fnadd(lhs:i32,rhs:i32)->i32{
lhs+rhs
}
fnadd_one(val:i32)->i32{
add(1,val)
}
```
### La boucle `for` revisitée
La dernière fonction à discuter est `find_min(tab)` qui retourne la valeur minimale se trouvant dans `tab`.
```rust
# const SIZE: usize = 9;
# fn read_command_line() -> [i32; SIZE] {
# [10, 32, 12, 43, 52, 53, 83, 2, 9]
# }
# fn check_size(size: usize) {
# if size == 0 {
# panic!("Size is of tab = 0.");
# }
# }
# fn min_i32(lhs: i32, rhs: i32) -> i32 {
# if lhs < rhs {
# lhs
# } else {
# rhs
# }
# }
fnfind_min(tab:[i32;SIZE])->i32{
check_size(SIZE);
letmutmin=i32::MAX;
fortintab{
min=min_i32(min,t);
}
min
}
# fn main() {
letmin=find_min(read_command_line());
println!("The minimal value is: {min}");
# }
```
Cette version du calcul du minimum contient une différence importante dans la syntaxe de la boucle `for`.
En effet, ici on itère pas sur un indice et on accède ensuite aux éléments du tableau.
La syntaxe
```rust,ignore
forvalintab
```
permet d'itérer directement sur les valeurs contenues dans `tab`. Au début de chaque tour de la boucle `for`,
val prend la valeur "courante" du tableau. A la fin du bloc du `for`, la valeur courante prend la valeur "suivante"
dans le tableau si elle existe. En fait le tableau est implicitement converti en *itérateur* (plus de détails plus tard sur le sujet).
Dans d'autres langages on appelle ça une boucle "for each" qui traduit en français signifie *pour chaque*.