MATA56 - Paradigmas de Linguagens de Programação
Universidade Federal da Bahia
Prof. Rodrigo Rocha <rodrigo@dcc.ufba.br>
É uma característica da implementação da linguagem. Ex.: existem compiladores e interpretadores de C.
Pascal
if c then begin b1 end else begin b2 end
C
if (c) { b1; } else { b2; }
LISP
(if c b1 b2)
Haskell
e | c = b1 | c2 = b2 | otherwise = b3
Fonte: http://rigaux.org/language-study/syntax-across-languages/CntrFlow.html#CntrFlowIfTheEls
código-fonte
(sintaxe concreta)
análise
léxica
sintática
árvore de sintaxe abstrata
(AST)
gerador
código-objeto
frontend
backend
outros atributos: posição na memória, tamanho (array, strings), número e tipo dos argumentos (funções)...
https://en.wikipedia.org/wiki/Memory_safety
var glob = 123; // 1 console.log(glob); // 2 function teste() { // 3 var x = 2; // 4 console.log(x); // 5 } // 6 glob = 456; // 7
Qual o escopo da variável glob?
Qual o escopo da variável x?
var glob = 123; // 1 console.log(glob); // 2 function teste() { // 3 var x = 2; // 4 console.log(x); // 5 } // 6 glob = 456; // 7
glob tem escopo global: é acessível de qualquer parte do programa, a princípio (existem exceções, como veremos)
x tem escopo local: só é acessível no bloco de código da função teste.
var glob = 123; // 1 console.log(glob); // 2 function teste() { // 3 var x = 2; // 4 console.log(x); // 5 } // 6 glob = 456; // 7
Qual é o ambiente de referenciamento da linha 7?
E da linha 5?
É o conjunto de nomes visíveis em uma região do programa.
/* 1 */ var glob = 1; /* 2 */ /* 3 */ function externa() { /* 4 */ var xext = 2; /* 5 */ /* 6 */ function interna() { /* 7 */ var xint = 3; /* 8 */ console.log(xext); /* 9 */ } /* 10 */ interna(); /* 11 */ } /* 12 */ externa();
JavaScript permite funções aninhadas ==> escopos aninhados.
O que vai acontecer ao executar a linha 8?
A variável xext faz parte do amb. de referenciamento da linha 8?
/* 1 */ var x = 1; /* 2 */ /* 3 */ function externa() { /* 4 */ var x = 2; /* 5 */ /* 6 */ function interna() { /* 7 */ var x = 3; /* 8 */ console.log(x); /* 9 */ } /* 10 */ interna(); /* 11 */ } /* 12 */ externa();
Na linha 8, o nome x se refere à variável declarada em qual linha?
/* 1 */ var x = 1; /* 2 */ /* 3 */ function externa() { /* 4 */ var x = 2; /* 5 */ /* 6 */ function interna() { /* 7 */ var x = 3; /* 8 */ console.log(x); /* 9 */ } /* 10 */ interna(); /* 11 */ } /* 12 */ externa();
A declaração de x na linha 4 mascara a variável x da linha 1 (sombreamento)
Qual o escopo das diferentes vinculações de x?
A vinculação entre argumentos e parâmetros geralmente se dá por posição (1o parâmetro recebe o 1o argumento etc.). Ex.:soma(3, 4)
Algumas linguagens admitem parâmetros nomeados, de forma que os argumentos podem ser passados em qualquer ordem. Ex.:soma(b=4, a=3)
Algumas linguagens permitem parâmetros opcionais com valores default. Ex.: soma(b=4) ou soma(3).
Algumas linguagens permitem número variável de argumentos. Ex.: soma(1, 2, 3, 4, 5, 6, 7).
Existem diversos mecanismos para passagem de parâmetros durante a chamada, de acordo com 2 dimensões:
o valor é transferido para a função (in) vs o valor é transferido da função para o chamador (out) ou ambos (inout)
o valor é copiado para a função vs. uma referência é passada para a função
Chamada por valor: o argumento é avaliado e copiado para a subrotina (in)
Chamada por referência: uma referência para o argumento é passada para a subrotina (in/out)
Chamada por valor-resultado: o argumento é copiado para a subrotina e, ao fim de sua execução, é copiado de volta para o chamador (in/out). Ex.: rede
Todos esses casos são estratégias de avaliação estrita: os argumentos de uma função são avaliados antes da chamada da função.
Considere o seguinte exemplo em C:
1 + 1 == 2 ? printf("A") : printf("B");
Se pensarmos no operador ternário (?:) como uma função de três parâmetros, ela segue uma avaliação estrita?
ternario(1 + 1 == 2, printf("A"), printf("B"))
Como criar a função ternario em C?
Avaliação não-estrita: os argumentos são avaliados apenas seu valor é requisitado. Aplicação: listas infinitas. Alguns tipos:
Chamada por nome: o texto do argumento é passado como parâmetro e avaliado dentro da função (in/out). Usado em Scala. Ver exemplo. #define em C. Aplicação: logging.
Chamada por necessidade: igual ao anterior, mas avalia parâmetro só uma vez (faz caching do resultado). Ex.: função fibonacci recursiva.
Nas linguagens com suporte ao paradigma funcional, uma função é um valor (assim como números, strings etc.)
Nesse caso dizemos que funções são cidadãos de primeira classe
Isso significa que é possível
atribuir uma função a uma variável
passar uma função como parâmetro para outra
criar funções que retornam funções
Esse tópico será detalhado na unidade sobre programação funcional
A sobrecarga ocorre quando há duas ou mais funções com o mesmo nome dentro do mesmo ambiente de referenciamento
A função chamada depende da lista de parâmetros
número de parâmetros
tipo dos parâmetros
Considere as duas declarações a seguir:
int soma(int a, int b)
float soma(float a, float b)
Uma chamada a soma(3, 5) invocará qual das funções?
E se for soma(3, 5.0f)? E se for soma(x, y), onde x e y são do tipo double?
Considere as duas declarações a seguir:
int fibonacci(int n);
long fibonacci(int n);
Considere a seguinte chamada:
long x = fibonacci(10)
Qual das funções será chamada? E se a chamada for:
float x = fibonacci(10)
Em C, não há como distinguir funções somente pelo tipo de retorno.