tipos e valores
TRANSCRIPT
Tipos e Valores
Prof: Sergio Souza Costa
Adaptado de © 2004, Programming Language Design Concepts
D.A. Watt, University of Glasgow
Sobre mim
Sérgio Souza CostaProfessor - UFMADoutor em Computação Aplicada (INPE)
https://sites.google.com/site/profsergiocosta/home
https://twitter.com/profsergiocosta
http://gplus.to/sergiosouzacosta
http://www.slideshare.net/skosta/presentations?order=popular
Roteiro
1. Tipos e valores2. Tipos primitivos3. Tipos compostos4. Sistema de tipos5. Tipos abstratos de dados
Tipos
Valores são agrupados por tipos de acordo com as operações poderão ser executadas sobre eles.
Tipos
Valores são agrupados por tipos de acordo com as operações poderão ser executadas sobre eles. Diferentes linguagens suportão diferente tipos de dados.
Tipos
Valores são agrupados por tipos de acordo com as operações poderão ser executadas sobre eles. Diferentes linguagens suportão diferente tipos de dados.
Ada: booleans, characters, enumerands, integers, real numbers, records, arrays, discriminated records, objects (tagged records), strings, pointers to data, pointers to procedures.C: enumerands, integers, real numbers, structures, arrays, unions, pointers to variables, pointers to functions.Java: booleans, integers, real numbers, arrays, objects.Haskell: booleans, characters, integers, real numbers, tuples, disjoint unions, lists, tipos recursivos.
Tipos
Tipo é um conjunto de valores: v é um valor de tipo T se v Є T.
Tipos
Tipo é um conjunto de valores: v é um valor de tipo T se v Є T.
E é uma expressão de tipo T se E leva a um valor do tipo T.
Tipos
Tipo é um conjunto de valores: v é um valor de tipo T se v Є T.
E é uma expressão de tipo T se E leva a um valor do tipo T. Um tipo é um conjunto de valores que exibe um comportamento uniforme sob operações associadas a este conjunto.
Tipos
Tipo é um conjunto de valores: v é um valor de tipo T se v Є T.
E é uma expressão de tipo T se E leva a um valor do tipo T. Um tipo é um conjunto de valores que exibe um comportamento uniforme sob operações associadas a este conjunto. Boolean {true, false}, Operações: and, or, not, etc
Tipos
Tipo é um conjunto de valores: v é um valor de tipo T se v Є T.
E é uma expressão de tipo T se E leva a um valor do tipo T. Um tipo é um conjunto de valores que exibe um comportamento uniforme sob operações associadas a este conjunto. Boolean {true, false}, Operações: and, or, not, etc {15, true, azul} é um tipo?
Tipos
A cardinalidade de um tipo T, escrito #T, e o número de valores do tipo T.● #Boolean = 2
Tipos
A cardinalidade de um tipo T, escrito #T, e o número de valores do tipo T.● #Boolean = 2
Classificação de tipos:○ Primitivos○ Compostos○ Recursivos
Tipos Primitivos
Valores primitivos são aqueles cujos valores são atômicos – não podem ser decompostos em valores mais simples.
Tipos Primitivos
Valores primitivos são aqueles cujos valores são atômicos – não podem ser decompostos em valores mais simples.
Tipo primitivo é onde os valores são primitivos.
Tipos Primitivos
Valores primitivos são aqueles cujos valores são atômicos – não podem ser decompostos em valores mais simples.
Tipo primitivo é onde os valores são primitivos.
Toda linguagem de programação possui tipos primitivos, e algumas permitem definir novos.
Tipos primitivos - Comuns
Boolean = {false, true} Character = {…, ‘A’, …, ‘Z’, …, ‘0’, …, ‘9’, …} Integer = {…, –2, –1, 0, +1, +2, …} Float = {…, –1.0, …, 0.0, +1.0, …}
Tipos primitivos - Comuns
Cardinalidades: #Boolean = 2 #Character = 128 (ASCII), 256 (ISO-Latin), or 32768 (Unicode) #Integer = max integer – min integer + 1
Note: Em algumas linguagens (ex. C), booleans e characters são inteiros.
Criando tipos primitivos
Ada permite definir novos tipos numéricos. Ada, C, Haskell permite criar nos tipos enumerados, simplismente a partir da enumeração seus valores.
Criando tipos primitivos
Em Ada é possível definir novos tipos númericos. ● Declaração:
type Population is range 0 .. 1000;● Conjunto de valores:
Population = {0, 1, …, 1000}● Cardinalidade:
#Population = 1001
Criando tipos primitivos
Em diversas linguagens é possível definir tipos de dados enumeráveis.
Criando tipos primitivos
Em diversas linguagens é possível definir tipos de dados enumeráveis.
C: enum Cor { VERMELHA, PRETA };
Ada:type Color is (VERMELHA, PRETA );
Haskelldata Color = Vermelha | Preta
Criando tipos primitivos - Atividade
1. Em Haskell, ADA e C, implementem o tipo booleano:
Valores: {Verdadeiro, Falso}
Operações: E, Ou, OuEx, Nao
2. Descreva o que achou sobre cada uma das linguagens3. Para casa: Pesquisem como fariamos isso em Ruby e Python
Tipos Compostos
Um valor composto ou estruturado é quando o seu valor é composto a partir de valores mais simples.
Tipos Compostos
Um valor composto ou estruturado é quando o seu valor é composto a partir de valores mais simples. Tipo composto é um tipo cujos valores são compostos.
Tipos Compostos
Um valor composto ou estruturado é quando o seu valor é composto a partir de valores mais simples.
Tipo composto é um tipo cujos valores são compostos.
Linguagens de programação (LP) suporta uma grande variedade deles.
Tipos Compostos
Podem ser entendidos por poucos conceitos:● Cartesian products (tuples, structures, records)● mappings (arrays)● disjoint unions (algebraic data types, discriminated
records, objects)● recursive types (lists, trees, etc.)
Produtos Cartesianos
● Por meio do produto cartesiano, valores de dois tipos (possivelmente diferentes) são emparelhados.
● Sejam S e T dois tipos quaisquer. O produto cartesiano SxT é definido como:
S x T = { (x,y) | x in S; y in T}
● Exemplo: boolean x integer = {..., (true, -1), (true, 0), (true, 1), ..., (false, -1), (false, 0), (false, 2), ...}
● Cardinalidade: #(SxT) = #S x #T
Produtos Cartesianos
Records (Ada), structures (C), e tuplas (Haskell) são exemplos de Produtos Cartesianos:
struct Point { x,y: double;
};
structures (C)type Point is record x: Double;
y: Double;
end record;
Records (Ada),
type Point = (Double,Double)
tuplas (Haskell) class Point: x = 0;y =0;
Class (Python),
Produtos Cartesianos - ADA
type Month is (jan, feb, mar, apr, may, jun,
jul, aug, sep, oct, nov, dec);
type Day_Number is range 1 .. 31;
type Date is record
m: Month;
d: Day_Number;
end record;
Declarações:
Uso:someday: Date := (jan, 1);
…put(someday.m+1); put("/"); put(someday.d);someday.d := 29; someday.m := feb;
Produtos Cartesianos -Haskell
someday = (jan, 1)(m,d) = somedayanotherday = (m + 1, d)
Valores:
data Month = Jan | Feb | Mar | Apr| May | Jun | Jul | Aug| Sep | Oct | Nov | Dectype Date = (Month, Int)
Date = Month X Integer= {Jan, Feb, …, Dec} X {…, –1, 0, 1, 2, …}
Uso:
Declarações:
Produtos Cartesianos - POO
Uma classe de objetos é um produto cartesiano de seus atributos. Os métodos são as operações válidas sobre este tipo.
class Point {public: Point (double x, double y); double x() { .. } double y() { .. }private: double x,y;};
Produtos Cartesianos
Algumas linguagens como Lua, não "definimos" novos tipos, apenas valores e construtores. Os produtos cartesianos são representados por tabelas. Ponto é do tipo tabela, com dois campos, x e y.
ponto = {x= 10, y= 20}
Java Script, se comporta de modo similar, entretanto neste caso são chamado do tipo objeto.
ponto = {x: 10, y: 20}
Uniões Disjuntas
Na união disjunta os valores são escolhidos de dois tipos (normalmente diferentes).
Sejam S e T dois tipos quaisquer. A união disjunta S+T é definida como:
S + T = {esquerda x | x in S} U {direita y | y in T} Exemplo:
S = {a,b,c} e T = {0,1} S + T = {esquerda(a), esquerda (b), esquerda(c), direita(0), direita(1)}
Cardinalidade:
#(S + T) = #S + #T
Uniões Disjuntas
union {
int exact;
float inexact;
};
Union em C
data Number = Exact Int | Inexact Float
Tipos algébricos em Haskell
type Accuracy is (exact, inexact);type Number (acc: Accuracy := exact) is record case acc of when exact => ival: Integer; when inexact => rval: Float; end case;end record;
Ada
Uniões Disjuntas - Haskell
Declaração data Number = Exact Int | Inexact Float
Valores: Number = Exact Integer + Inexact Float … Exact(–2) Exact(–1) Exact 0 Exact 1 Exact 2 …… Inexact(–1.0) … Inexact 0.0 … Inexact 1.0 …
Cardinalidade: #Number = #Integer + #Float
Cada valor consiste de uma tag, junto ou com um valor inteiro (se a tag is Exact) ou um valor Float (se a tag é Inexact).
Uniões Disjuntas - Haskell
pi = Inexact 3.1416 rounded :: Number -> Integerrounded Exact i = i
rounded Inexact r = round r
>rounded pi >3
Uso:
Unions e cartesianos - C
Descrição de um símbolo, em um interpretador.
typedef enum { int_t, float_t ,string_t} TYPE;
union m_value { int int_value; float float_value; char* str_value;} ;struct symbol { const char* name; union m_value* val; TYPE t;};
Mapeamentos
Define uma função de um conjunto para outro (array e função).
Sejam S e T dois tipos quaisquer. Os mapeamentos S -> T são definidos como:
S -> T = {m(x) | x in S => m(x) in T} Exemplo:
Integer -> Char = ... U { ..., -1 -> ´#´, 0->´%´, 1-> ´&´, ...} U {..., -1 -> ´z´ 0->´y´, 1-> ´w´, ...} U ...
Cardinalidade de todos mapeamentos:
#(S -> T) = (#T)#S
Exemplo, {u, v} -> {a, b, c} existem 3^2 = 9 possibilidade
Mapeamentos - Arrays
Arrays é um tipo de mapeamento finito de um index e valor.Se um array é do tipo T e seu index é do tipo S. Então o array é um
mapeamento do tipo S -> T.
Em C e Java, o indice deve estar na faixa entre {0, 1, …, n–1}.
Em Ada, pode ser qualquer tipo primitivo (excessão tipos reais)
Em Lua, os indices podem ser qualquer um dos tipos existentes.
Mapeamentos - Arrays
Arrays é um tipo de mapeamento finito de um index e valor.Se um array é do tipo T e seu index é do tipo S. Então o array é um
mapeamento do tipo S -> T.
Em C e Java, o indice deve estar na faixa entre {0, 1, …, n–1}.
Em Ada, pode ser qualquer tipo primitivo (excessão tipos reais)
Em Lua, os indices podem ser qualquer um dos tipos existentes.
Esse tipo de
mapeamento so
existe em
linguagens
imperativas.
Array - Ada
● Declaração: type Color is (red, green, blue);type Pixel is array (Color) of Boolean;
● Uso: p: Pixel := (true, false, true);c: Color;…p(c) := not p(c);
Array - Ada
● Valores: Pixel = Color -> Boolean = {red, green, blue} -> {false, true} viz: {red -> false, green -> false, blue -> false} {red -> false, green -> false, blue -> true} {red -> false, green -> true, blue -> false} {red -> false, green -> true, blue -> true} {red -> true, green -> false, blue -> false} {red -> true, green -> false, blue -> true} {red -> true, green -> true, blue -> false} {red -> true, green -> true, blue -> true}
● Cardinalidade: #Pixel = (#Boolean)#Color = 23 = 8
Tabelas - Lua
Tabelas com indices numéricos, 0 a N
t1 = {"maria", "joana"}
print (t1[1], t2[1])
Tabelas com indices não numéricos,
a1 = { nome = "maria", matricula = 123}
print (a1["nome"], a1["matricula"])
print (a1.nome, a1.matricula)
Mapeamento - Função
Funções é outro tipo de mapeamento. Uma função mapea argumentos para resultado.
Se uma função tem um unico argumento do tipo S e o resultado é do tipos T, a função é um mapeamento do tipo S -> T.
Mapeamento - Função - Ada
Definição: function is_even (n: Integer) return Boolean is begin return (n mod 2 = 0); end;
Tipo:Integer -> Boolean
Valores: {…, 0 -> true, 1 -> false, 2 -> true, 3 -> false, …}
Mapeamento - Função -Haskell
Definição: is_even n = (mod n 2 == 0)
Tipo
Integer -> Boolean
Valores: {…, 0 -> true, 1 -> false, 2 -> true, 3 -> false, …}
Tipos Recursivos
Um tipo recursivo é definido em termos de si.
Exemplos de tipos recursivos:● listas● árvores● números naturais
A cardinalidade de tipos recursivos é infinita.
Tipos Recursivos - Naturais
Peano, descreveu os axiomas dos números naturais, onde um número natural ou é Zero ou é o seu Succ.
Tipos Recursivos - Naturais
Exemplos:
0 -> Zero
1 -> Succ (Zero)
2- > Succ ( Succ (Zero))
3- > Succ ( Succ ( Succ (Zero)))
...
Numeros Naturais - C
typedef struct Nat {struct Nat* succ;
}* Nat;
Nat Zero () {return NULL;
}
Nat Succ (Nat a) {Nat n = malloc (sizeof (Nat));n->succ = a;return n;
}
Definição da estrutura. Observe a recursão.
Função que define o Zero
Função que define o seu Succ
Numeros Naturais -C
Nat sum (Nat a, Nat b) {
if (a == Zero () )
return b;
else
return Succ ( sum (a->succ,b));
}
Nat mult (Nat a, Nat b) {
if (a == Zero () )
return Zero ();
else
return sum (b, (mult (b, a->succ)));
}
Numeros Naturais -C
void show (Nat a) {
if (a == Zero ()) {
printf ("Zero ()");
}
else {
printf ("Succ (");
show (a->succ);
printf (")");
}
}
Uso:
Nat a = Succ (Succ (Zero ()));show (a) -> Succ (Succ (Zero ()))
Numeros Naturais - Haskell
data Nat = Zero | Succ Nat deriving (Show)
soma :: Nat -> Nat -> Natsoma Zero n = nsoma (Succ m) n = Succ (soma m n)
mult :: Nat -> Nat -> Natmult Zero m = Zeromult (Succ m) n = soma n (mult n m)
Tipos Recursivos - Lista
Uma lista é uma sequencia de 0 ou mais elementos.
O tamanho de uma lista é seu número de elementos. ● Uma lista vazia não possui nenhum elemento.
Uma lista não vazia consiste de uma cabeça (primeiro elemento) e a calda (todos elementos que não são cabeça).
Uma lista é homogenea se todos seus componentes são do mesmo tipo, caso contrário são homogeneas.
Tipos Recursivos - Lista - Haskell
Declaração:data IntList = Nil | Cons Int IntList
Construções:>Nil
>Cons 2 (Cons 3 (Cons 5 (Cons 7 Nil)))
Haskell ja tem um tipo lista nativos[Int] [String] [[Int]]
Construções : [] [2,3,5,7]["cat","dog"][[1],[2,3]]
Tipos Recursivos - Lista - Haskell
ATIVIDADE: Codifiquem as funções soma, produto e tamanho em Haskell.
O que se conclui com relação as funções soma e produto ?
Tipos Recursivos - Lista - Ada
Declaraçõestype IntNode;
type IntList is access IntNode;
type IntNode is record
head: Integer;
tail: IntList;
end record;
Construtor new IntNode'(2,
new IntNode'(3,
new IntNode'(5,
new IntNode'(7, null)))
Strings
● Seqüência de 0 ou mais caracteres.● Não existe consenso sobre sua classificação.● Strings são tipos primitivos ou compostos?● Python, ML, Lua são tipos primitivos● Em Haskell é uma lista de caracter● Em C, vetor de caracter.● Java trata strings como objetos da classe String.
Sistema de tipos
●Agrupando valores em tipos, permite o programador descrever dados de forma efetiva. ○Uma disciplina de tipos também previne os
programas de operações sem sentido.●Checagem de tipos assegura que uma dada
operação é aplicada a operandos adequados.●As checagem de tipos podem ser executadas em
tempo de compilação ou em tempo de execução.●Um erro de tipo ocorre se o programa executa uma
operação com tipos incopativeis, tais como multiplicar uma string por um valor booleano
Checagem de tipos
Classificação de Linguagens do sistema de tipos:● Estaticamente tipadas - toda variável e parâmetro tem um
tipo fixo escolhido pelo programador. (Pascal, C, C++, Haskell, Ada).
● Dinamicamente tipadas - apenas valores têm tipos fixos. Variáveis e parâmetros não possuem um tipo associado, mas podem assumir valores de diferentes tipos em diferentes trechos do programa. (Smalltalk, Clipper, SNOBOL).
Linguagem estaticas
Exemplo em C:
int max (int a, int b) {
if (a > b) return a;
else return b
}
max (4, 5)
max (3.5,3.1)
Qual a principal limitação ?Conhecem algum recurso que pode diminuir essa limitação ?
Linguagem dinâmicas
● Exemplo em Lua:
function max (a, b)
if a > b then return a
else return b end
end
print (max (3.2, 3.6))
print (max ("a","b"))
Qual a principal vantagem das linguagens dinâmicas ?Qual a principal desvantagem das linguagens dinâmicas ?
Estáticos Vs Dinâmico
● Tipagem dinâmica implica em baixa performance em tempo de execução.
● Segurança é outra vantagem de linguagens estaticamente tipadas.
● A grande vantagem de linguagens dinamicamente tipadas é a flexibilidade.○ Ex: LUA, Python, JavaScript.
Inferência de tipos
Haskell é uma linguagem estática, porém ela possui um recurso conhecido como "inferência de tipos"
Este recurso permite que o programador não explicite o tipo de uma função.
f x = 0.6 * x
Ao invés disso:
f :: Double-> Double
f x = 2 * x
Erro de tipos
● É a aplicação de um operador a um operando de um tipo inapropriado○ Atribuir um int para uma função que espera um float nas
primeiras versões de C● Se todas as vinculações de variáveis a tipos forem estáticas
na linguagem, a verificação de tipos pode ser feita toda em tempo de compilação
● Em linguagens dinâmicas (JavaScript, PHP) isso só pode ser feito em tempo de execução
Tipagem forte
● Uma das idéias de projeto de LPs surgida na década de 70○ é uma característica bastante apreciada em LPs
● Existe um pouco de subjetividade com relação a esta terminologia.
● Uma linguagem é dita fortemente tipada se os erros de tipo são sempre detectados○ seja em tempo de compilação quanto de execução
● Linguagens dinâmicas tendem a ter um tipo mais fraco que linguagens estáticas.
Tipagem forte
● Fortran 95 não é fortemente tipada○ uso da funcionalidade Equivalence
● Ada é quase fortemente tipada○ uso da funcionalidade Unchecked_Conversion
● C e C++ não são fortemente tipadas● ML e Haskel são fortemente tipados● Java e C# são quase fortemente tipadas
○ Existem algumas coerções (conversões "automáticas")
Tipagem forte e coerção
● Regras de coerção possuem um efeito importante no valor da verificação de tipos.○ o valor da tipagem forte é reduzido de acordo com as
coerções● LPs com muitas coerções (C, C++, Fortran) são menos
confiáveis que LPs com poucas (Ada, Java, C#)● Java e C# possuem cerca de metade das coerções de C++,
por exemplo.
// convertido implicitamente para inteiro
int a = 10.5;
PRINCÍPIO DA COMPLETUDE DO TIPO
Em principio um valor de qualquer tipo pode:● atribuido● composto com outros valores● passado com um argumento ( procedure ou function)● retornado como resultado de uma função
PRINCÍPIO DA COMPLETUDE DO TIPO
Em principio um valor de qualquer tipo pode:● atribuido● composto com outros valores● passado com um argumento ( procedure ou function)● retornado como resultado de uma função
Algumas linguagens restringem essas operações sobre alguns valores.
PRINCÍPIO DA COMPLETUDE DO TIPO
Em principio um valor de qualquer tipo pode:● atribuido● composto com outros valores● passado com um argumento ( procedure ou function)● retornado como resultado de uma função
Algumas linguagens restringem essas operações sobre alguns valores.
Valores de primeira classe não possuem restrições.
PRINCÍPIO DA COMPLETUDE DO TIPO
● Valores de segunda classe - podem ser passados como argumentos, mas não podem ser avaliados, atribuídos, ou fazer parte de valores compostos. (abstrações de função e procedimento em Pascal).
● Valores de primeira classe - podem ser passados com argumentos, avaliados, atribuídos e fazer parte de valores compostos. (tipos primitivos em Pascal)
● Em linguagens como Lua, Haskell, Python, JavaScript, Ruby, ML e Miranda, valores são tratados sem distinção.
PRINCÍPIO DA COMPLETUDE DO TIPO
Funções como valores de primeira classe, exemplo JavaScript (JQuery). Passando função como parametro.
$(“button”).click(function(){
facaAlgo();
});
Tipos de dados definem a forma como um dado deve ser armazenado ou recuperado, bem como os possíveis valores que ele pode assumir e as operações que podem ser efetuadas sobre os mesmos.
Um tipo abstrato de dados (TAD) é a especificação matemática de um conjunto de dados e das operações que podem ser executadas sobre esses dados.
O conceito de tipo de dado abstrato é dissociado do hardware.
Tipo Abstrato de Dados (TAD)
John Guttag, grande contribuição na formalização dos TAD.
J.V. Guttag, The Specification and Application to Programming of Abstract Data Types,Ph.D. Thesis, Dept. of Computer Science, University of Toronto (1975).
Um tipo abstrato de dados (TAD) é a especificação matemática de um conjunto de dados e das operações que podem ser executadas sobre esses dados.
O conceito de tipo de dado abstrato é dissociado do hardware.
John Guttag, grande contribuição na formalização dos TAD.
J.V. Guttag, The Specification and Application to Programming of Abstract Data Types,Ph.D. Thesis, Dept. of Computer Science, University of Toronto (1975).
A expressão tipo abstrato de dados normalmente refere-se ao tipos definidos pelo usuário.
Tipo Abstrato de Dados (TAD)
TAD define o que cada operação faz, mas não como faz.
Assim, um mesmo tipo abstrato de dados pode ser concretizado (ou implementado) de diversas formas.
Tipo Abstrato de Dados (TAD)
•TADs são implementadas através da combinação de:
–Tipos primitivos
–Tipos compostos.
–Arrays
–Ponteiros
Tipo Abstrato de Dados (TAD)
•Encapsulam e "protegem" os dados
•Foi o conceito básico para a definição de orientação a objetos.
•Quatro tipos diferentes de operações
–Construtoras
–Consultoras
–Atualizadoras
–Destrutoras
Tipo Abstrato de Dados (TAD)
Dados
Operações(consultoras)
Operações(construtoras)
Operações(atualizadoras)
Operações(destrutoras)
ClienteTAD
Tipo Abstrato de Dados (TAD)
Dados
Operações(consultoras)
Operações(construtoras)
Operações(atualizadoras)
Operações(destrutoras)
ClienteTAD
Tipo Abstrato de Dados (TAD)
O exemplo mais simples de um cliente é a função main.
As operações em um tipo abstrato de dados protegem os dados da aplicação cliente.
Modificações nos dados não acarretará mudanças no código da aplicação cliente.
Mais a frente no curso, verão que o paradigma de programação orientado a objeto teve como base os tipos de dados abstratos.
Tipo Abstrato de Dados (TAD)
Referências
Programming Language Design Concepts [Paperback]. David A. Wat
Abstract Data Types and the Development of Data Structures