Seguinte: Parâmetros Especiais Acima: Modelo de Ambientes Anterior: Âmbito Léxico
Índice remissivo

Âmbito Dinâmico

A criação de variáveis globais em Common Lisp deve ser feita usando as formas especiais defconstant para criar constantes, defvar para criar variáveis inicializáveis uma única vez e defparameter para criar variáveis inicializáveis várias vezes. Esta diferença é relevante sobretudo durante a fase de desenvolvimento e depuração de programas.

> (defconstant acelaracao-gravidade 9.8)
ACELARACAO-GRAVIDADE
> (defvar *y*)
*Y*
> (defparameter *z* 10)
*Z*

Note-se a convenção adoptada para as variáveis globais de usar nomes compreendidos entre um par de asteriscos. Quando se definem constantes essa convenção não se aplica.

O facto de podermos ter variáveis globais introduz uma alteração nas regras de avaliação. Tínhamos visto que as variáveis que eram parâmetros de funções (e, como tal, as variáveis introduzidas por um let) tinham âmbito léxico, ou seja, apenas podiam ser referidas dentro da região textual que as introduziu. No entanto, as variáveis globais como aceleracao-gravidade, *y* ou *z* podem ser referidas de qualquer ponto do programa, fazendo com que o seu âmbito passe a ser vago. No entanto, apesar de ser possível referênciar a variável *y*, será produzido um erro quando tentarmos determinar o seu valor, uma vez que ele ainda está indefinido. Será preciso ligarmos um valor àquela variável antes de a podermos avaliar e, para isso, podemos usar um let.

> (defvar *y*)
*Y*
> (defun teste () (+ *y* *y*))
TESTE
> (teste)
Error: Unbound variable: *Y*
> (let ((*y* 10)) (teste))
20
>*y*
Error: Unbound variable: *Y*

Repare-se que apesar de, momentaneamente, termos atribuido um valor à variável *y* por intermédio de um let, ela perdeu esse valor assim que terminou o let. A duração da variável *y* é, assim, dinâmica. Apenas as variáveis léxicas possuem duração indefinida. Variáveis como *y* e *z* dizem-se especiais e possuem âmbito vago e duração dinâmica. Esta combinação dá origem a um comportamento que se designa de âmbito dinâmico.

Um dos aspectos mais críticos na utilização de variáveis de âmbito dinâmico é o facto de, geralmente, não ser suficiente ler o código de um programa para perceber o que é que ele vai fazer--é também preciso executá-lo. O seguinte exemplo explica este ponto.

Imaginemos as seguintes definições:

> (let ((x 2))
    (defun soma-2 (y) 
      (+ x y)))
SOMA-2
> (let ((x 1000))
    (soma-2 1))
3

> (defparameter *x* 1)
*X*
> (let ((*x* 2))
    (defun soma-2 (y)
      (+ *x* y)))
SOMA-2
> (let ((*x* 1000))
    (soma-2 1))
1001

O primeiro exemplo envolve apenas variáveis léxicas. Daí que baste observar o texto da função soma-2 para se perceber que a variável x usada em (+ x y) toma sempre o valor 2.

No segundo exemplo, a única diferença está no facto de a variável *x* ser especial. Nesta situação a função soma-2 não usa o valor de *x* que existia no momento da definição da função, mas sim o valor de *x* que existe no momento da execução da função. Desta forma, já não é suficiente observar o texto da função soma-2 para perceber o que ela faz. Por este motivo, o uso excessivo de variáveis dinâmicas pode tornar um programa difícil de ler e, consequentemente, difícil de desenvolver e difícil de corrigir.


Seguinte: Parâmetros Especiais Acima: Modelo de Ambientes Anterior: Âmbito Léxico
Índice remissivo

Copyright António Leitão, 1995