Buscar

Paradigmas de Linguagens de Programação - Aula 3

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.

Continue navegando