Com o escopo dinâmico, um receptor pode acessar as variáveis do chamador. Código pseudo-C:
void foo()
{
print(x);
}
void bar()
{
int x = 42;
foo();
}
Como nunca programei em um idioma que suporte o escopo dinâmico, pergunto-me quais seriam alguns casos de uso do mundo real para o escopo dinâmico.
Respostas:
Uma aplicação muito útil do escopo dinâmico é a passagem de parâmetros contextuais sem a necessidade de adicionar novos parâmetros explicitamente a todas as funções em uma pilha de chamadas
Por exemplo, o Clojure oferece suporte ao escopo dinâmico via encadernação , que pode ser usado para reatribuir temporariamente o valor da
*out*
impressão. Se você reconectar*out*
, todas as chamadas para impressão no escopo dinâmico da ligação serão impressas no seu novo fluxo de saída. Muito útil se, por exemplo, você desejar redirecionar toda a saída impressa para algum tipo de log de depuração.Exemplo: no código abaixo, a função do-stuff será impressa na saída de depuração, e não na saída padrão, mas observe que eu não precisei adicionar um parâmetro de saída ao do-stuff para ativar isso ....
Observe que as ligações do Clojure também são localizadas por thread, portanto, você não tem problemas com o uso simultâneo desse recurso. Isso torna as ligações consideravelmente mais seguras que (ab) usando variáveis globais para o mesmo objetivo.
fonte
(Isenção de responsabilidade: nunca programei em um idioma de escopo dinâmico)
O escopo é muito mais fácil de implementar e potencialmente mais rápido. Com o escopo dinâmico, apenas a tabela de um símbolo é necessária (as variáveis disponíveis no momento). Apenas lê nesta tabela de símbolos para tudo.
Imagine em Python a mesma função.
Quando ligo para barra, coloco x na tabela de símbolos. Quando chamo foo, pego a tabela de símbolos atualmente usada para bar e empurro-a para a pilha. Então chamo foo, que x passou para ele (provavelmente tendo sido colocado na nova tabela de símbolos ao chamar a função). Depois de sair da função, tenho que destruir o novo escopo e restaurar o antigo.
Com o escopo dinâmico, isso não é necessário. Eu só preciso saber as instruções para as quais preciso retornar quando a função terminar, pois nada precisa ser feito na tabela de símbolos.
fonte
O tratamento de exceções na maioria dos idiomas utiliza escopo dinâmico; quando ocorrer uma exceção, o controle será transferido de volta para o manipulador mais próximo na pilha de ativação (dinâmica).
fonte
return
declarações na maioria dos idiomas usam escopo dinâmico, porque retornam o controle ao chamador na pilha?Não tenho 100% de certeza se essa é uma correspondência exata, mas acho que pelo menos chega perto o suficiente em um sentido geral para mostrar onde pode ser útil quebrar ou alterar as regras de escopo.
A linguagem Ruby vem da classe de modelo ERB, que por exemplo no Rails é usada para gerar arquivos html. Se você usar, fica assim:
Os
binding
ponteiros acessam variáveis locais à chamada do método ERB, para que possa acessá-las e usá-las para preencher o modelo. (O código entre os EOFs é uma string, a parte entre <% =%> avaliada como código Ruby pelo ERB e declararia seu próprio escopo como uma função)Um exemplo do Rails ainda melhor demonstra isso. Em um controlador de artigo, você encontraria algo assim:
O arquivo index.html.erb poderia então usar a variável local
@articles
assim (neste caso, a criação de um objeto ERB e a ligação são tratadas pela estrutura do Rails, para que você não a veja aqui):Portanto, pelo uso de uma variável de ligação, Ruby permite executar um e o mesmo código de modelo em contextos diferentes.
A classe ERB é apenas um exemplo de uso. O Ruby permite, em geral, obter o estado real de execução com ligações de variáveis e métodos, usando a ligação Kernel #, que é muito útil em qualquer contexto em que você deseja avaliar um método em outro contexto ou deseja manter um contexto para uso posterior.
fonte
Os casos de uso para escopo dinâmico são IHMO os mesmos para variáveis globais. O escopo dinâmico evita alguns dos problemas com variáveis globais, permitindo uma atualização mais controlada da variável.
Alguns casos de uso em que consigo pensar:
É claro que o escopo dinâmico não é "absolutamente necessário", mas alivia o ônus de ter que passar dados vagabundos pela cadeia de chamadas ou de implementar proxies globais inteligentes e gerenciadores de contexto.
Porém, novamente, o escopo dinâmico é útil ao lidar com tipos de elementos que muitas vezes são tratados como globais (registro em log, saída, alocação / gerenciamento de recursos, etc.).
fonte
Praticamente não há. Espero que você, por exemplo, nunca use a mesma variável duas vezes.
Agora, como você chama foo e bar da mesma função?
Isso é efetivamente semelhante ao simples uso de uma variável global e é ruim pelos mesmos motivos.
fonte
x = 42; foo(); x = '42'; bar();
?