Muitas linguagens escolhem o caminho de tornar a atribuição uma declaração, e não uma expressão, incluindo Python:
foo = 42 # works
if foo = 42: print "hi" # dies
bar(foo = 42) # keyword arg
e Golang:
var foo int
foo = 42 # works
if foo = 42 { fmt.Printn("hi") } # dies
Outros idiomas não têm atribuição, mas ligações de escopo, por exemplo, OCaml:
let foo = 42 in
if foo = 42 then
print_string "hi"
No entanto, let
é uma expressão em si.
A vantagem de permitir a atribuição é que podemos verificar diretamente o valor de retorno de uma função dentro do condicional, por exemplo, neste snippet Perl:
if (my $result = some_computation()) {
say "We succeeded, and the result is $result";
}
else {
warn "Failed with $result";
}
O Perl também escopo a declaração apenas para essa condicional, o que a torna muito útil. Ele também avisará se você atribuir dentro de uma condicional sem declarar uma nova variável lá - if ($foo = $bar)
avisará, if (my $foo = $bar)
não avisará .
Fazer a atribuição em outra declaração geralmente é suficiente, mas pode trazer problemas de escopo:
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 depende muito dos valores de retorno para verificação de erros. Portanto, permite que um condicional leve uma instrução de inicialização:
if result, err := some_computation(); err != nil {
fmt.Printf("Failed with %d", result)
}
fmt.Printf("We succeeded, and the result is %d\n", result)
Outros idiomas usam um sistema de tipos para proibir expressões não-booleanas dentro de um condicional:
int foo;
if (foo = bar()) // Java does not like this
É claro que isso falha ao usar uma função que retorna um booleano.
Vimos agora diferentes mecanismos de defesa contra atribuição acidental:
- Proibir atribuição como expressão
- Usar verificação de tipo estático
- A atribuição não existe, temos apenas
let
ligações
- Permitir uma declaração de inicialização, não permitir atribuição de outra forma
- Proibir atribuição dentro de um condicional sem declaração
Classifiquei-os em ordem crescente de preferência - atribuições dentro de expressões podem ser úteis (e é simples contornar os problemas do Python tendo uma sintaxe de declaração explícita e uma sintaxe de argumento nomeada diferente). Mas não há problema em impedi-los, pois há muitas outras opções para o mesmo efeito.
O código sem erros é mais importante que o código conciso.