Baixe o app para aproveitar ainda mais
Prévia do material em texto
Paradigmas de Linguagens de Programação Variáveis – Nomes, Vinculações, Escopo PPGCOMP – UNIFACS Prof. Sergio Martins Fernandes sergio.fernandes@unifacs.br 71 99958-0897 Roteiro • Introdução • Nomes • Variáveis • O conceito de vinculação - binding • Escopo • Escopo e tempo de vida • Ambientes de referenciamento • Constantes nomeadas Introdução • Este capítulo aborda as questões semânticas fundamentais referentes a variáveis • As linguagens de programação imperativas são abstrações da arquitetura de computadores subjacente de von Neumann – Memória • Contém instruções e variáveis – Processador • Executa operações que modificam o conteúdo da memória Nomes • Antes de discutir variáveis, alguns conceitos sobre nomes • Nomes se aplicam a variáveis, mas também a funções, operações, subprogramas, parâmetros, e outros elementos de linguagens de programação • Questões de projeto primárias para nomes: Formato, limitação de tamanho dos nomes – Os nomes são sensíveis a capitalização? – As palavras especiais da linguagem são palavras reservadas ou palavras-chave? Nomes • Formato – Se forem muito pequenos, podem não ser conotativos – Exemplos: • FORTRAN 95: máximo de 31 • C#, Ada e Java: sem limite e todos os caracteres são significativos • C++: sem limite, mas os implementadores às vezes o impõem Nomes • Caracteres especiais – PHP: todos os nomes de variáveis devem começar com cifrão ($) – Perl: todos os nomes de variáveis começam com caracteres especiais, que especificam o seu tipo – Ruby: nomes de variáveis que começam com @ são variáveis de instância; as que começam com @@ são variáveis de classe Nomes • Sensibilidade à capitalização – Nomes em linguagens baseadas em C são sensíveis à capitalização – Nomes em diversas outras linguagens não são sensíveis à capitalização – Desvantagem: legibilidade (nomes que são parecidos, mas são diferentes) • Em C++, Java e C#, o problema não pode ser evitado porque muitos dos nomes pré- definidos incluem tanto letras maiúsculas quanto minúsculas (por exemplo, IndexOutOfBoundsException) Nomes • Palavras especiais – São usadas para tornar os programas mais legíveis ao nomearem as ações a serem realizadas – Uma palavra-chave é uma palavra especial apenas em alguns contextos – por exemplo, em Fortran – Real VarName (Real é um tipo de dado acompanhado de um nome, portanto Real é uma palavra-chave) – Real = 3.4 (Real é uma variável) – Em Fortran, é possível escrever a seguinte sintaxe: Real Integer Integer Real – Uma palavra reservada é uma palavra especial que não pode ser usada como um nome – Problema em potencial com as palavras reservadas: se houver muitas, o usuário tem dificuldade para inventar nomes (por exemplo, COBOL tem 300 palavras reservadas!) Variáveis • Abstrações, por uma linguagem, de células de memória da máquina – Em alguns casos a abstração é bem próxima das características das células • Exemplo: variável inteira, representada diretamente por uma ou mais células de memória – Em outros casos, abstração é bem distante das células de memória • Exemplo: matriz tridimensional, que demanda uma função de mapeamento para suportar a abstração • Uma variável pode ser caracterizada como um conjunto de seis atributos: – Nome – Endereço – Valor – Tipo – Tempo de vida – Escopo Atributos de variáveis • Nome – Nem todas as variáveis têm – Em C++, por exemplo, variáveis podem ser criadas dinamicamente com o operador new, e acessadas através de ponteiros. Exemplo: – int *intnode; // Create a pointer – intnode = new int; // Create the heap-dynamic variable – . . . – delete intnode; // Deallocate the heap-dynamic variable to which intnode points 100 meuAluno 100 public class Aluno { public String nome; public void getTurmas( ) { ... } } Public método qualquerdeQualquerOutraClasse { Aluno meuAluno, outroAluno; ‘ meuAluno = new Aluno(); meuAluno.getTurmas(); outroAluno = meuAluno; outroAluno.getTurmas(); } 100 outroAluno Atributos de variáveis • Endereço - é o endereço de memória de máquina ao qual ela está associada – Uma variável pode ter diferentes endereços em diferentes momentos durante a execução – Exemplo: variável local alocada dinamicamente a cada vez que um subprograma é acionado – Instanciações distintas da mesma variável – Quando dois nomes de variáveis podem ser usados para acessar a mesma posição de memória, elas são chamadas de apelidos (aliases) – Apelidos são criados por ponteiros, variáveis de referência, etc. – Apelidos são um problema para a legibilidade (um leitor do programa deve sempre se lembrar de todos eles) Atributos de variáveis • Tipo - determina a faixa de valores que a variável pode armazenar e o conjunto de operações definidas para valores do tipo – Exemplo: • O tipo int em Java especifica uma faixa de valores de -2147483648 a 2147483647 e as operações aritméticas para adição, subtração, multiplicação divisão e módulo • Valor - é o conteúdo da(s) célula(s) de memória associada(s) a ela – Deve-se pensar em célula de memória abstrata – As células físicas, atualmente, são bytes de 8 bits cada • Insuficientes para armazenar variáveis – Célula abstrata de memória – célula física ou coleção de células associadas a uma variável – Por conta de comandos de atribuição de valor – O lado esquerdo (l-value) de uma variável é seu endereço – O lado direito (r-value) de variável é seu valor O conceito de vinculação (binding) • Uma vinculação é uma associação, entre um atributo e uma entidade (como entre uma variável e seu tipo ou valor) ou entre uma operação e um símbolo • Tempo de vinculação é o momento no qual uma vinculação ocorre Possíveis tempos de vinculação • Tempo de projeto de linguagem - vincula símbolos de operadores a operações, como a vinculação do símbolo * à operação de multiplicação • Tempo de projeto de linguagem – por exemplo, vincula tipo int a uma faixa de valores possíveis • Tempo de compilação – vincula uma variável a um tipo em C ou Java • Tempo de ligação (link) –vincula uma chamada a subprograma numa biblioteca ao código do subprograma • Tempo de carga na memória – vincula uma variável static de C ou C++ a uma célula de memória • Tempo de execução – vincula uma variável de um método Java a uma célula de memória (em um objeto instanciado em tempo de execução) Um exemplo • Declaração Java count = count + 5; – O tipo de count é vinculado em tempo de compilação – O conjunto de valores possíveis de count é vinculado em tempo de projeto do compilador – O significado do operando + é vinculado em tempo de compilação, quando os tipos dos operandos são determinados – A representação interna do literal 5 é vinculada em tempo de projeto do compilador – O valor de count é vinculado em tempo de execução da sentença Por que é o momento da vinculação é relevante? • Entender em que momento se dão as vinculações é pré-requisito para entender a semântica de uma linguagem de programação – Particularmente quando se utiliza recursos específicos da linguagem, como chamada de funções, métodos, instanciação de objetos, etc. Vinculações estáticas e dinâmicas • Uma vinculação é estática se ocorre pela primeira vez antes do tempo de execução e permanece inalterada ao longo da execução do programa • Uma vinculação é dinâmica se ocorre pela primeira vez durante o tempo de execução ou pode ser mudada ao longo do curso da execução do programa Vinculações ao tipo: estáticas e dinâmicas • Antes que uma variável possa ser referenciada num programa, deve ser vinculada a um tipo de dado • Aqui há duas questões importantes: – Como o tipo é especificado• Explicita ou implicitamente – Quando a vinculação ocorre • Estática ou dinamicamente Vinculação estática: declaração explícita/implícita de variáveis • Uma declaração explícita é uma sentença em um programa que lista nomes de variáveis e especifica que elas são de um certo tipo • Uma declaração implícita é uma forma de associar variáveis a tipos por meio de convenções padronizadas, em vez de por sentenças de declaração (primeira aparição de um nome de variável em um programa) – Efetuada pelo compilador ou intérprete da linguagem – Pode ser efetuada através de convenções de nomenclatura, como em Fortran (variáveis cujo nome começa com i, j, k, l, m, n são inteiras) – Pode ser efetuada também por inferência, como em C# • A declaração da variável deve incluir uma atribuição de valor, cujo tipo se torna o tipo da variável • Exemplo: var sum = 0; var total = 0.0; var name = "Fred"; • FORTRAN, BASIC e Perl têm declarações implícitas – Fortran tem explícita e implícita, mas a declaração implícita pode ser evitada com a cláusula IMPLICIT NONE – Vantagem: facilidade de escrita – Desvantagem: confiabilidade – programador pode não declarar variável por esquecimento, e compilador assume tipo indevido. Erros difíceis de detectar – Perl tem recursos para evitar esse problema • Em Perl, – Qualquer nome que comece com $ é um escalar, do tipo string ou valor numérico – Se o nome começa com @, é um vetor – Se começa com %, é uma estrutura hash Vinculação estática: declaração explícita/implícita de variáveis Vinculação de tipos dinâmica • Vinculação de tipos dinâmica (JavaScript e PHP) • Tipo da variável não é definido por sentença de declaração, nem por convenção de nomenclatura • Especificada por meio de uma sentença de atribuição por exemplo, JavaScript list = [2, 4.33, 6, 8]; list = 17.3; • A sentença de atribuição também vincula a variável a um endereço e uma célula de memória • Porque tipos distintos requerem espaço distinto • O tipo da variável pode mudar em em tempo de execução • Vantagem: flexibilidade (unidades de programa genéricas) • Desvantagens: • Custo elevado • Detecção de erros de tipo pelo compilador é difícil Vinculação à célula de memória: tempo de vida • Vinculações de armazenamento e tempo de vida – Alocação - obter uma célula de um conjunto de células disponíveis – Liberação – colocar a célula de volta no conjunto • O tempo de vida de uma variável é o tempo durante o qual ela está vinculada a uma posição específica da memória Categorias de variáveis por tempo de vida • Estáticas - vinculadas a células de memória antes do início da execução de um programa e permanecem vinculadas a essas mesmas células de memória até que a execução do programa termine – Vantagens: eficiência – Desvantagens: redução da flexibilidade, pois não é possível a recursão; utilização da memória não pode ser otimizada através de compartilhamento Categorias de variáveis por tempo de vida (Heap versus stack) STACK Espaço da memória do computador Armazena temporariamente variáveis criadas por funções Estrutura de dados tipo FILO (first in last out) Gerenciada e otimizada pela CPU HEAP Ocupa um espaço maior da memória do computador Não gerenciada automaticamente pela CPU Espaço de memória alocado e desalocado explicitamente pelos programas Categorias de variáveis por tempo de vida • Dinâmicas de pilha (stack dynamic) – Vinculações de armazenamento são criadas quando suas sentenças de declaração são elaboradas, mas cujos tipos são estaticamente vinculados – Elaboração = alocação de memória e execução do processo de vinculação, conforme indicado na declaração da variável – A declaração é elaborada quando a execução alcança o código com o qual a declaração é efetuada – Todos os atributos exceto o endereço são vinculados estaticamente – Exemplo: variáveis declaradas em métodos Java são elaboradas quando o método é chamado e desalocadas quando a execução do método é concluída • Vantagem: – permite recursão, pois cada cópia do subprograma recursivo terá sua própria cópia das variáveis locais –Desvantagens: – Sobrecarga da alocação e liberação – Subprogramas não são sensíveis ao histórico Categorias de variáveis por tempo de vida • Dinâmicas do monte (heap-dynamic) explícitas - Alocadas e liberadas por instruções explícitas em tempo de execução • Referenciadas apenas por ponteiros ou variáveis de referência, por exemplo, objetos dinâmicos em C++ (via new e delete), todos os objetos em Java – Ou seja, essas variáveis não tem nome • Em linguagens como C++, o tipo da variável é definido estaticamente, e o endereço de memória é alocado dinamicamente • Vantagem: prevê o gerenciamento de armazenamento dinâmico • Desvantagem: ineficientes e não confiáveis Categorias de variáveis por tempo de vida • Dinâmicas do monte implícitas – Alocadas e liberadas por sentenças de atribuição – Todas as variáveis em APL; todas cadeias e matrizes em Perl, JavaScript e PHP • Exemplo: highs = [74, 84, 86, 90, 71]; – Independentemente da variável highs ter sido usada antes, com qualquer outro objetivo, ela agora é um vetor de 5 valores numéricos • Vantagem: – Flexibilidade, pois viabilizam a escrita de código altamente genérico • Desvantagens: – Ineficiente, pois todos os atributos são dinâmicos – Perda de detecção de erro Atributos de variáveis: escopo • O escopo de uma variável é a faixa de sentenças nas quais a variável é visível. – Uma variável é visível numa determinada declaração se pode ser referenciada nessa declaração • Uma variável é local a uma unidade de programa ou bloco se tiver sido declarada nessa unidade ou bloco. • As variáveis não locais de uma unidade ou de um bloco de programa são aquelas que estão visíveis, mas não são declaradas nessa unidade ou bloco • Variáveis globais são uma categoria especial de variáveis não locais • As regras de escopo de uma linguagem determinam como uma ocorrência em particular de um nome é associada com uma variável Escopo estático • Conceito criado por ALGOL 60 • Definido antes da execução do programa • Baseado no texto do programa • Para ligar um nome de referência a uma variável, você (ou o compilador) deve encontrar a declaração da variável do código fonte • Processo de busca: busca de declarações , primeiro localmente, depois em escopos cada vez maiores, até encontrar o nome dado Escopo estático • Algumas linguagens permitem subprogramas aninhados, que criam escopos estáticos aninhados (por exemplo, Ada, JavaScript, Fortran 2003 e PHP) – Linguagens derivadas de C não permitem escopos aninhados para subprogramas • Mas permitem escopos aninhados para declarações de classes aninhadas e blocos • Exemplo em JavaScript: Qual o valor de y? function big() { function sub1() { var x = 7; sub2(); } function sub2() { var y = x; } var x = 3; sub1(); } A variável x aqui é a declarada em big Blocos • Um método de criar escopos estáticos em unidades de programa - do ALGOL 60 • Exemplo em C: void sub() { int count; while (...) { int count; count++; ... } … } – Note que o código é legal em C and C++, mas ilegal em Java e C# • Em C++, Java e C#, variáveis podem ser declaradas em sentenças for – O escopo dessas variáveis é restrito à construção for Dentro deste bloco, a variável count que é acessada é a desta declaração. A variável count declarada em sub() fica oculta. Ordem de declaração • C99, C++, Java e C# permitem que as declarações de variáveis aparecam em qualquer lugar que uma sentença poderia aparecer em uma unidade de programa – Em C99, C++ e Java, o escopo de todas as variáveis locais é de suas declarações até o final dos blocos – Em C#, o escopo de quaisquer variáveisdeclaradas em um bloco é o bloco inteiro, independentemente da posição da declaração • C# ainda requer que todas as variáveis sejam declaradas antes de serem usadas • Ou seja, na prática, só pode ser usada após sua declaração Escopo global • C, C++, PHP e Python permitem uma estrutura de programa que é uma sequência de definição de funções, nas quais as definições de variáveis podem aparecer fora das funções • Definições de variáveis fora das funções num determinado arquivo criam variáveis globais, que podem potencialmente ser vistas nessas funções. • C, C++ – Uma variável global em C é visível implicitamente em todas as funções definidas subsequentemente no arquivo, exceto para aquelas que incluem uma declaração de variável local com o mesmo nome. Escopo global (continuação) • PHP – Programas são embutidos em documentos XHTML – O escopo de uma variável (implicitamente) declarada em uma função é local à função – O escopo das variáveis globais se estende de suas declarações até o fim do programa, mas pulam sobre quaisquer definições de funções subsequentes • Variáveis globais podem ser acessadas em uma função por meio do vetor $GLOBALS • Python – Uma variável global pode ser referenciada em uma função, mas uma variável global pode ter valores atribuídos a ela apenas se ela tiver sido declarada como global na função Avaliação do escopo estático • Funciona bem em muitas situações • Problemas: – Em muitos casos, fornece mais acesso tanto a variáveis quanto a subprogramas do que é necessário – Poucos recursos para especificar restrições de forma concisa – Como um programa evolui (restruturação, refatoração), a estrutura inicial é destruída e as variáveis locais muitas vezes se tornam globais Escopo dinâmico • Baseado na sequência de chamadas de subprogramas, não em seu relacionamento espacial uns com os outros • As referências a variáveis são conectadas com as declarações por meio de buscas pela cadeia de chamadas a subprograma que forçaram a execução até esse ponto Exemplo de escopo • Big chama Sub1 • Sub1 chama Sub2 • Sub2 usa X Big - declaração de X Sub1 - declaração de X - ... chama Sub2 ... Sub2 ... - referência a X - ... ... chama Sub1 … Exemplo de escopo • Escopo estático – Referência a X é ao X declarado em Big • Escopo dinâmico – Referência a X é ao X declarado em Sub • Avaliação do escopo dinâmico: – Vantagem: as desvantagens do escopo estático – Desvantagens: 1. Programas são mais difíceis de ler 2. Execuções distintas de um programa podem implicar em acesso a variáveis não locais distintas Ambientes de referenciamento • O ambiente de referenciamento de uma sentença é a coleção de todas as variáveis visíveis na sentença • Em uma linguagem de escopo estático, é composto pelas variáveis declaradas em seu escopo local mais a coleção de todas as variáveis de seus escopos ancestrais visíveis • Um subprograma está ativo se sua execução começou, mas ainda não terminou • Em uma linguagem de escopo dinâmico, é composto pelas variáveis declaradas localmente, mais as variáveis de todos os outros subprogramas que estão atualmente ativos Constantes nomeadas • Uma constante nomeada é uma variável que está vinculada a um valor apenas uma vez • Vantagens: legibilidade e confiabilidade • Usadas para parametrizar programas • A vinculação de valores a constantes nomeadas podem ser estáticas (chamadas de constantes de manifesto) ou dinâmicas • Linguagens: – FORTRAN 95: expressões constantes – Ada, C++ e Java: expressões de qualquer tipo – C# tem dois tipos, readonly e const • Os valores de const são vinculados em tempo de compilação • Os valores de readonly são dinamicamente vinculados Resumo • Sensibilidade à capitalização e a relação de nomes com palavras especiais são problemas para os nomes • Variáveis são caracterizadas por: nome, endereço, valor, tipo, tempo de vida e escopo • A vinculação é a associação de atributos com entidades de programa. • Variáveis escalares podem ser categorizadas em: estáticas, dinâmicas da pilha, dinâmica do monte explícitas e dinâmicas do monte implícitas. • Tipagem forte permite detectar todos os tipos de erros.
Compartilhar