Escopo estático

A resposta de Phil Jones (He / Him) para Quais são as vantagens do escopo dinâmico?

Aqui está um pequeno programa

#incluir

usando espaço para nome std;

int a = 4, b = 5;

void printab (void) {cout << a << "" << b << "\ n";}

void bac () {

int a = 6;

printab ();

}

void cdy () {

int a = 5, b = 7;

printab ();

bac ();

}

int main () {

int b = 6;

printab ();

cdy ();

}

(uma)

O que será exibido na tela se o escopo estático for usado?

Ans 4 5

4 5

4 5

b)

O que será exibido na tela se o escopo for dinâmico?

Ans

4 6

5 7

6 7

Não posso explicar melhor do que isso:

Escopo estático vs. dinâmico

O escopo estático seria mais rápido e previsível no lado do compilador, pois todo o escopo é resolvido no momento da compilação.

Quase todas as linguagens modernas usam escopo lexical (estático), porque é difícil trabalhar com escopo dinâmico.

Com escopo lexical, um nome sempre se refere ao seu ambiente lexical local. Com escopo dinâmico, cada identificador possui uma pilha global de ligações. A introdução de uma variável local com o nome x envia uma ligação para a pilha x global (que pode estar vazia), que é disparada quando o fluxo de controle sai do escopo. Avaliar x em qualquer contexto sempre gera a ligação superior. Em outras palavras

Aqui está um exemplo do lisp comum que tem escopo lexical e dinâmico.

* Primeiro escopo lexical.

> (defina 'regular 5) ;; A variável regular está vinculada ao valor 55 > (desabilitar check-regular () regular) ;; Criamos uma função check-regular que retorna o valor da variável regularCHECK-REGULAR > (verifique regularmente)5 > (deixe ((regular 6)) (verifique regularmente)) ;; Criamos um novo escopo em que a variável regular é vinculada a 6 e chama nossa função de verificação regular. Retorna 5 porque esse era o valor quando regular quando a verificação regular era definida.5

* Aqui está um exemplo com escopo dinâmico

> (defvar * especial * 5) ;; defvar é usado para definir uma variável com escopo dinâmico*ESPECIAL*> (desmarque check-special () * especial *)CHECK-SPECIAL> (seleção especial)5> (deixe ((* especial * 6)) (cheque especial)) ;; Criamos um novo escopo em que a variável * special * é vinculada a 6. Como esse é um escopo dinamicamente e o valor local (6) é enviado para a pilha global6

Bem, todo mundo deu uma boa explicação do escopo dinâmico versus escopo estático, mas estou escrevendo esta resposta para minha compreensão. Se eu estiver errado em algum lugar, aponte….

  • Então, primeira pergunta é o que você quer dizer com escopo?
  • Escopo refere-se à área ou região do seu programa na qual os identificadores (variáveis, funções ou objetos) podem ser acessados.
  • Agora, surge a segunda pergunta: como o escopo é definido?
  • Depende da linguagem.
  • Em C, C ++ ou no escopo da maioria das linguagens é definido usando chaves curley, ou seja, {your code ……}
  • No recorte python é usado.
  • Em javascript, também são utilizados chavetas de curley, mas o cenário de escopo é um pouco diferente de C / C ++.
  • Agora, alguns exemplos para entender qual é o escopo do hack?
#incluir int main () {// Início do escopo externo int x = 1 {// Início do escopo interno int y = 2;printf ("% d% d", x, y); // Imprimir 1,2 // End Inner Scope; }// Fim do escopo externo}

A declaração printf () imprimirá 1,2

E se eu fizer isso?

#incluir int main () {// Início do escopo externo int x = 1 {// Início do escopo interno int y = 2; // End Inner Scope; }printf ("% d", y); // gera erro// Fim do escopo externo}

Agora, a declaração printf () gera erro porque a variável y pode ser acessada no escopo interno onde é definida, não na região externa.

Assim, na região externa y não pode ser acessada, isso é tudo sobre o escopo. O ESCOPO determina em qual região sua variável pode ser acessada ou não.

Agora, de onde veio o escopo lexical e o dinâmico?

Considere o caso em que definimos duas ou mais variáveis ​​com o mesmo nome em escopo diferente. Por exemplo

// BLOCO EXTERIORint x = 10; // Variável global --- pode ser acessada em qualquer lugar no códigofunction func2 () {// Bloco Interno retornar x; // x é 10 ou 23?}function func1 () {// Bloco Internoint x = 47; // Novamente, a variável 'x' é definida em outro escopo. retornar func2 ();}void main () {// bloco interno printf ("% d", func1 ()); retornar 0;}

Agora, qual valor de 'x' func2 () retornará? Para isso, os programadores definem alguma regra de escopo ao projetar a linguagem.

Em resumo, no escopo estático, a hierarquia de escopo é de cima para baixo, no caso de bloco aninhado, o bloco mais interno pode acessar variáveis ​​do bloco externo, mas vice-versa não é verdadeiro. Por isso, produzimos 10.

De acordo com a regra de escopo, func2 () procurará a variável x em seu próprio escopo, mas x não é o deles. Fucn2 () procurará a variável x em seu escopo externo. No escopo externo func1 () está presente, void main () está presente e a variável global x também está presente ... Agora, func2 () encontra o valor x, por isso, retorna 10, não 47, porque func2 () não pode procurar no escopo de func1 ().

Escopo Dinâmico

Enquanto no escopo dinâmico, a saída é 47, porque a saída depende da ordem em que sua função é chamada. Para entender isso, você deve saber como a pilha de execução é criada. Em toda linguagem programmig quando fuction é chamada, uma pilha é criada, que armazena o estado da função e é destruída assim que a função concluir sua execução.

Sempre a função main () é chamada primeiro, portanto, toda vez que você executa seu programa, uma pilha será criada.

No nosso programa acima, main () func1 () é chamado por isso que é empurrado para empilhar e fucn2 () é chamado e também é empurrado. Agora, func2 () pesquisará a variável em seu próprio escopo. no escopo externo, mas no ambiente mais recente em que é chamado. Portanto, aqui func2 () procurará no escopo de fucn1 (). Aqui, func2 () encontra x variável como 47 e, portanto, retorna 47.

Na função Short in lexical scope, procure a variável em que ela está definida, enquanto na função dinâmica do escopo procure a variável em que é chamada.

Espero que a resposta seja um pouco concisa e clara. Se você tiver dúvidas, faça um comentário.

Um escopo é uma seção do programa de tamanho máximo na qual nenhuma alteração de ligação ou pelo menos nenhuma redeclaração é permitida. As regras de escopo, ou seja, estáticas ou dinâmicas, determinam como a referência aos nomes é associada às variáveis.

O escopo estático é definido em termos da estrutura física do programa. A determinação do escopo de uma variável é feita pelo compilador, examinando o texto do programa. O escopo da variável é o bloco fechado onde a variável é declarada. A referência aos nomes das variáveis ​​é resolvida usando a regra “aninhado mais próximo”.

foo () { int i = 10; {int i = 6; {i = 5; // Aqui, i é referenciado à variável declarada // na linha 4 (a mais próxima do aninhado). } }}

Escopo estático em chamadas de função aninhadas.

contagem int = 10;void func2 () { printf ("In func2% d", count) "; // Pega o valor global count = 10}void func1 () { contagem int = 20; func2 ();}int main (){ func1 (); retornar 0;}

As regras de escopo dinâmico são encontradas principalmente em idiomas interpretados. No escopo dinâmico, a ligação depende do fluxo de controle no tempo de execução e da ordem em que as funções são chamadas. A referência aos nomes é resolvida usando a regra "ligação ativa mais próxima".

Para o código acima, a variável count em func2 assume o valor de count de func1, isto é, a saída impressa neste caso será em func2 20. Isso ocorre porque, durante o tempo de execução, o func2 é chamado de func1, que por sua vez é chamado de main; No func2, para resolver a contagem de nomes, ele olha novamente para a pilha e aceita a associação mais recente.

Conforme mencionado por Jack Mudge, o escopo dinâmico é adequado para idiomas usados ​​em cálculos matemáticos.

C, C ++ usa escopo estático, enquanto o Lisp suporta escopo dinâmico.

Na maioria das linguagens imperativas (quase todos os alunos aprendem isso primeiro: C, Java, Python etc.), o escopo dinâmico não é substancialmente valioso, pois a memória e o escopo são mais facilmente manipulados pelo pedido. No entanto, ao programar em um estilo funcional (idealmente em uma linguagem adequadamente funcional), o escopo dinâmico tem algumas vantagens.

Em particular, nas linguagens funcionais, existe um conceito de efeitos colaterais: quando uma função altera uma variável ou causa algum efeito além de simplesmente retornar um valor, isso é chamado de efeito colateral. Em muitos casos, é desejável evitar. (Isso também é verdade em linguagens imperativas, mas é, perdoe o trocadilho, imperativo em linguagens funcionais.) Em um contexto imperativo, você pode criar uma variável global que é alterada à medida que o programa avança. O escopo dinâmico permite um padrão de design semelhante sem efeitos colaterais. Isso é comum no Lisp, embora muitos dialetos do Lisp tenham escopo dinâmico e lexical, realizado declarando ligações dinâmicas. (Existem outros casos de uso; esse é apenas um caso muito comum.)

Algo semelhante ao escopo dinâmico também é o padrão em matemática. Considere as funções f (x) = x + g (y); g (y) = x +2. Ao avaliar f (2), geralmente é convencional avaliar isso como f (2) = 2 + g (y) = 2 + 2 +2 = 6. (É mais fácil ver isso em provas ou problemas que envolvem ordenação e lógica. Como resultado disso, muitos cálculos matemáticos também são muito mais simples ou requerem menos recursos se o escopo dinâmico for usado.

Há desvantagens também, no entanto. O mais óbvio, que é levantado quase toda vez que essa pergunta é discutida, é que pode ser mais difícil saber o que sua variável contém. Talvez você não consiga facilmente provar onde é modificado ou qual valor conterá em uma determinada linha de código. Na prática, isso não é um problema: as pessoas geralmente têm boas intuições sobre código, e problemas semelhantes ocorrem na maioria das linguagens de script com digitação simples. (No Python, você não sabe que tipo de objeto foi passado como uma string, basta usá-lo como uma string e lidar com erros, se eles acontecerem.)

Outra desvantagem do escopo dinâmico é que ele pode limitar os namespaces. Com o escopo dinâmico, todas as variáveis ​​são atribuídas explicitamente no bloco atual ou efetivamente recebidas do escopo global. Isso significa que, em programas grandes, as convenções de nomenclatura precisam ser seguidas cuidadosamente para evitar sobreposição nas variáveis ​​dinâmicas.