1.1.3 Avaliando Combinações de Operadores
Um de nossos objetivos neste capítulo é isolar questões sobre o pensamento processual. Como um caso em questão, consideremos que, ao avaliar combinações de operadores, o próprio interpretador está seguindo um procedimento.
- Para avaliar uma combinação de operadores, faça o seguinte:
- Avalie as expressões de operando da combinação.
- Aplique a função indicada pelo operador aos argumentos que são os valores dos operandos.
Mesmo essa regra simples ilustra alguns pontos importantes sobre os processos em geral. Em primeiro lugar, observe que a primeira etapa determina que, para realizar o processo de avaliação de uma combinação, devemos primeiro realizar o processo de avaliação em cada operando da combinação. Assim, a regra de avaliação é recursiva por natureza; ou seja, inclui, como uma de suas etapas, a necessidade de invocar a própria regra.
Observe como a ideia de recursão pode ser usada sucintamente para expressar o que, no caso de uma combinação profundamente aninhada, seria visto como um processo bastante complicado. Por exemplo, avaliando
requer que a regra de avaliação seja aplicada a quatro combinações diferentes. Podemos obter uma imagem desse processo representando a combinação na forma de uma árvore, conforme mostrado na figura 1.1. Cada combinação é representada por um nó com ramificações correspondentes ao operador e aos operandos da combinação que dele decorrem. Os nós terminais (ou seja, nós sem ramificações derivadas deles) representam operadores ou números. Vendo a avaliação em termos de árvore, podemos imaginar que os valores dos operandos percolam para cima, começando nos nós terminais e depois combinando em níveis cada vez mais altos. Em geral, veremos que a recursão é uma técnica muito poderosa para lidar com objetos hierárquicos semelhantes a árvores. Na verdade, a forma de "filtrar os valores para cima" da regra de avaliação é um exemplo de um tipo geral de processo conhecido como acumulação de árvore.
Figura 1.1 Representação em árvore, mostrando o valor de cada subexpressão.
A seguir, observe que a aplicação repetida da primeira etapa nos leva ao ponto em que precisamos avaliar, não combinações, mas expressões primitivas como numerais ou nomes. Cuidamos dos casos primitivos, estipulando que
- os valores dos numerais são os números que eles nomeiam, e
- os valores dos nomes são os objetos associados a esses nomes no ambiente.
O principal ponto a ser observado é o papel do ambiente na determinação do significado dos nomes nas expressões. Em uma linguagem interativa como JavaScript, não faz sentido falar do valor de uma expressão como x + 1 sem especificar qualquer informação sobre o ambiente que forneceria um significado para o nome x. Como veremos no capítulo 3, a noção geral de ambiente como um contexto no qual a avaliação ocorre terá um papel importante em nossa compreensão da execução do programa.
Observe que a regra de avaliação fornecida acima não trata de declarações. Por exemplo, avaliando const x = 3; não aplica um operador de igualdade = a dois argumentos, um dos quais é o valor do nome x e o outro é 3, uma vez que o objetivo da declaração é justamente associar x a um valor. (Ou seja, const x = 3; não é uma combinação.)
As letras em const são renderizadas em negrito para indicar que é uma palavra-chave em JavaScript. Palavras-chave carregam um significado particular e, portanto, não podem ser usadas como nomes. Uma palavra-chave ou uma combinação de palavras-chave em uma instrução instrui o interpretador JavaScript a tratar a instrução de uma maneira especial. Cada uma dessas formas sintáticas tem sua própria regra de avaliação. Os vários tipos de instruções e expressões (cada um com sua regra de avaliação associada) constituem a sintaxe da linguagem de programação.