De nombreux langages choisissent la voie pour faire de l'affectation une instruction plutôt qu'une expression, y compris Python:
foo = 42 # works
if foo = 42: print "hi" # dies
bar(foo = 42) # keyword arg
et Golang:
var foo int
foo = 42 # works
if foo = 42 { fmt.Printn("hi") } # dies
D'autres langues n'ont pas d'affectation, mais plutôt des liaisons de portée, par exemple OCaml:
let foo = 42 in
if foo = 42 then
print_string "hi"
Cependant, let
c'est une expression elle-même.
L'avantage de permettre l'affectation est que nous pouvons vérifier directement la valeur de retour d'une fonction à l'intérieur du conditionnel, par exemple dans cet extrait de code Perl:
if (my $result = some_computation()) {
say "We succeeded, and the result is $result";
}
else {
warn "Failed with $result";
}
Perl étend en outre la déclaration à cette conditionnelle uniquement, ce qui la rend très utile. Il avertira également si vous affectez à l'intérieur d'un conditionnel sans y déclarer une nouvelle variable - if ($foo = $bar)
avertira, if (my $foo = $bar)
ne le fera pas.
Faire l'affectation dans une autre déclaration est généralement suffisant, mais peut poser des problèmes de portée:
my $result = some_computation()
if ($result) {
say "We succeeded, and the result is $result";
}
else {
warn "Failed with $result";
}
# $result is still visible here - eek!
Golang s'appuie fortement sur les valeurs de retour pour la vérification des erreurs. Il permet donc à un conditionnel de prendre une instruction d'initialisation:
if result, err := some_computation(); err != nil {
fmt.Printf("Failed with %d", result)
}
fmt.Printf("We succeeded, and the result is %d\n", result)
D'autres langues utilisent un système de types pour interdire les expressions non booléennes à l'intérieur d'un conditionnel:
int foo;
if (foo = bar()) // Java does not like this
Bien sûr, cela échoue lors de l'utilisation d'une fonction qui renvoie un booléen.
Nous avons maintenant vu différents mécanismes pour se défendre contre une affectation accidentelle:
- Interdire l'affectation en tant qu'expression
- Utiliser la vérification de type statique
- L'affectation n'existe pas, nous n'avons que des
let
liaisons
- Autoriser une instruction d'initialisation, interdire l'affectation sinon
- Interdire l'affectation dans un conditionnel sans déclaration
Je les ai classés par ordre croissant de préférence - les affectations à l'intérieur des expressions peuvent être utiles (et il est simple de contourner les problèmes de Python en ayant une syntaxe de déclaration explicite et une syntaxe d'argument nommée différente). Mais il est permis de les interdire, car il existe de nombreuses autres options dans le même sens.
Le code sans bogue est plus important que le code laconique.