1.1.6 Expressões Condicionais e Predicados
O poder expressivo da classe de funções que podemos definir neste ponto é muito limitado, porque não temos como fazer testes e realizar diferentes operações dependendo do resultado de um teste. Por exemplo, não podemos declarar uma função que calcula o valor absoluto de um número testando se o número é não-negativo e tomando diferentes ações em cada caso de acordo com a regra:
Esse construto é uma análise de caso e pode ser escrito em JavaScript usando uma expressão condicional como:1
Carregando playground de código...
que poderia ser expresso em português como "Se x é maior ou igual a zero, retorne x; caso contrário, retorne -x."
A forma geral de uma expressão condicional é:
predicado ? expressão-consequente : expressão-alternativa
Expressões condicionais começam com um predicado - ou seja, uma expressão cujo valor é true ou false, dois valores booleanos distintos em JavaScript. Os expressões booleanas primitivas true e false avaliam trivialmente para os valores booleanos verdadeiro e falso, respectivamente. O predicado é seguido por um ponto de interrogação, a expressão-consequente, dois-pontos e, finalmente, a expressão-alternativa.
Para avaliar uma expressão condicional, o interpretador começa avaliando o predicado da expressão. Se o predicado é avaliado como verdadeiro, o interpretador avalia a expressão-consequente e retorna seu valor como o valor da condicional. Se o predicado é avaliado como falso, ele avalia a expressão-alternativa e retorna seu valor como o valor da condicional.
A palavra predicado é usada para operadores e funções que retornam verdadeiro ou falso, bem como para expressões que avaliam para verdadeiro ou falso. A função de valor absoluto abs faz uso do predicado primitivo >=, um operador que recebe dois números como argumentos e testa se o primeiro número é maior ou igual ao segundo número, retornando verdadeiro ou falso de acordo.
Se preferirmos lidar com o caso zero separadamente, podemos especificar a função que calcula o valor absoluto de um número escrevendo:
Em JavaScript, expressamos uma análise de caso com múltiplos casos aninhando expressões condicionais como expressões alternativas dentro de outras expressões condicionais:
Carregando playground de código...
Parênteses não são necessários ao redor da expressão alternativa x === 0 ? 0 : - x, porque a forma sintática da expressão condicional é associativa à direita. O interpretador ignora espaços e quebras de linha, aqui inseridos para legibilidade para alinhar os ? e : sob o primeiro predicado da análise de caso.
A forma geral de uma análise de caso é:
p₁
? e₁
: p₂
? e₂
...
: pₙ
? eₙ
: expressão-alternativa-final
Chamamos um predicado pᵢ junto com sua expressão consequente eᵢ de uma cláusula. Uma análise de caso pode ser vista como uma sequência de cláusulas, seguida por uma expressão alternativa final.
De acordo com a avaliação de expressões condicionais, uma análise de caso é avaliada primeiro avaliando o predicado p₁. Se seu valor for falso, então p₂ é avaliado. Se o valor de p₂ também for falso, então p₃ é avaliado. Este processo continua até que um predicado seja encontrado cujo valor seja verdadeiro, caso em que o interpretador retorna o valor da expressão consequente correspondente da cláusula como o valor da análise de caso. Se nenhum dos p for encontrado como verdadeiro, o valor da análise de caso é o valor da expressão alternativa final.
Operadores Lógicos
Além de predicados primitivos como >=, >, <, <=, === e !== que são aplicados a números, existem operações de composição lógica, que nos permitem construir predicados compostos. Os três mais frequentemente usados são:
-
Conjunção Lógica: expressão₁
&&expressão₂Esta operação expressa conjunção lógica, significando aproximadamente o mesmo que a palavra em português "e". Assumimos que esta forma sintática é açúcar sintático para:
expressão₁
?expressão₂:false -
Disjunção Lógica: expressão₁
||expressão₂Esta operação expressa disjunção lógica, significando aproximadamente o mesmo que a palavra em português "ou". Assumimos que esta forma sintática é açúcar sintático para:
expressão₁
?true:expressão₂ -
Negação Lógica:
!expressãoEsta operação expressa negação lógica, significando aproximadamente o mesmo que a palavra em português "não". O valor da expressão é verdadeiro quando a expressão é avaliada como falso, e falso quando a expressão é avaliada como verdadeiro.
Observe que && e || são formas sintáticas, não operadores; sua expressão do lado direito nem sempre é avaliada. O operador !, por outro lado, segue a regra de avaliação da seção 1.1.3. É um operador unário, o que significa que recebe apenas um argumento, enquanto os operadores aritméticos e predicados primitivos discutidos até agora são binários, recebendo dois argumentos. O operador ! precede seu argumento; nós o chamamos de operador prefixo. Outro operador prefixo é o operador de negação numérica, um exemplo do qual é a expressão - x nas funções abs acima.
Como exemplo de como esses predicados são usados, a condição de que um número x esteja no intervalo 5 < x < 10 pode ser expressa como:
x > 5 && x < 10
A forma sintática && tem precedência mais baixa que os operadores de comparação > e <, e a forma sintática de expressão condicional tem precedência mais baixa que qualquer outro operador que encontramos até agora, uma propriedade que usamos nas funções abs acima.
Como outro exemplo, podemos declarar um predicado para testar se um número é maior ou igual a outro como:
Carregando playground de código...
ou alternativamente como:
Carregando playground de código...
A função maior_ou_igual, quando aplicada a dois números, se comporta da mesma forma que o operador >=. Operadores unários têm precedência mais alta que operadores binários, o que torna os parênteses neste exemplo necessários.
Exercícios
Exercício 1.1
Abaixo está uma sequência de instruções. Qual é o resultado impresso pelo interpretador em resposta a cada instrução? Suponha que a sequência deve ser avaliada na ordem em que é apresentada.
10;
5 + 3 + 4;
9 - 1;
6 / 2;
2 * 4 + (4 - 6);
const a = 3;
const b = a + 1;
a + b + a * b;
a === b;
b > a && b < a * b ? b : a;
a === 4
? 6
: b === 4
? 6 + 7 + a
: 25;
2 + (b > a ? b : a);
(a > b
? a
: a < b
? b
: -1)
*
(a + 1);
Os parênteses ao redor das expressões condicionais nas últimas duas instruções são necessários porque a forma sintática de expressão condicional tem precedência mais baixa que os operadores aritméticos + e *.
Exercício 1.2
Traduza a seguinte expressão para JavaScript:
Exercício 1.3
Declare uma função que recebe três números como argumentos e retorna a soma dos quadrados dos dois números maiores.
Exercício 1.4
Observe que nosso modelo de avaliação permite aplicações cujas expressões de função são expressões compostas. Use esta observação para descrever o comportamento de a_plus_abs_b:
Carregando playground de código...
Exercício 1.5
Ben Bitdiddle inventou um teste para determinar se o interpretador com o qual ele está lidando está usando avaliação de ordem aplicativa ou avaliação de ordem normal. Ele declara as seguintes duas funções:
Carregando playground de código...
Então ele avalia a instrução:
test(0, p());
Que comportamento Ben observará com um interpretador que usa avaliação de ordem aplicativa? Que comportamento ele observará com um interpretador que usa avaliação de ordem normal? Explique sua resposta. (Suponha que a regra de avaliação para expressões condicionais é a mesma se o interpretador está usando ordem normal ou aplicativa: A expressão do predicado é avaliada primeiro, e o resultado determina se deve avaliar a expressão consequente ou a expressão alternativa.)
[1] Condicionais em JavaScript completo aceitam qualquer valor, não apenas um booleano, como resultado da avaliação da expressão do predicado. Os programas neste livro usam apenas valores booleanos como predicados de condicionais.
[2] "Interpretado como verdadeiro ou falso" significa isto: Em JavaScript completo, condicionais podem aceitar qualquer valor como resultado da avaliação da expressão predicado (veja a nota de rodapé na seção 4.1.2 para detalhes). Os programas neste livro usam apenas valores booleanos como predicados de condicionais.
📝 Encontrou algo errado nesta página?
Sua ajuda é muito importante para melhorar a qualidade da tradução!
🐛 Encontrou um erro?
Se você encontrou:
- Erro de tradução (palavra incorreta, termo técnico errado)
- Erro de ortografia ou gramática
- Link quebrado
- Código de exemplo que não funciona
- Problema de formatação
❓ Tem uma dúvida?
Se você tem:
- Dúvida sobre o conteúdo desta seção
- Pergunta sobre um conceito do SICP
- Dificuldade em entender algum exemplo
- Questão sobre a tradução de algum termo
💡 Tem uma sugestão de melhoria?
Se você quer sugerir:
- Melhoria na explicação
- Exemplo adicional
- Recurso visual (diagrama, ilustração)
- Qualquer outra ideia
🌍 Quer discutir a tradução?
Se você quer debater:
- Escolha de tradução de algum termo
- Consistência de terminologia
- Nuances do português
Obrigado por ajudar a melhorar o SICP.js PT-BR! ✨