Erlang- Progamação Sequencial -
Luıs Nogueira
Departamento Engenharia Informatica
Instituto Superior de Engenharia do Porto
Erlang – p. 1
Introducao
• Linguagem funcional para sistemas concorrentes edistribuídos
• Desenvolvida pela Ericsson• Necessidade de encontrar uma linguagem para grandes
sistemas de telecomunicações◦ Distribuída◦ Concorrente◦ Tolerante a falhas◦ Substituição de código em run time
Erlang – p. 2
Principais caracterısticas
• Sintaxe declarativa - livre de efeitos colaterais (ex: variáveisglobais)
• Concorrente - processos requerem pouca memória• Soft real-time - tempos de resposta na ordem dos
milisegundos• Operação contínua - substituição de código em run time• Robusta - detecção de erros em run time• Gestão de memória - garbage collection em tempo real• Distribuída - processos comunicam por passagem de
mensagens• Integração - facilidade de usar/ser usada com outras
linguagens
Erlang – p. 3
Linguagem funcional
• Trata a computação como a avaliação de funçõesmatemáticas
• Funções como caixas negras◦ Para o mesmo input, sempre o mesmo output◦ Podemos “esquecer” o seu interior◦ Facilita a reutilização de código
• Variáveis não alteram o seu valor após instanciação• Funções de ordem superior - aceitam funções como
parâmetro
Erlang – p. 4
Conselho para as aulas praticas
• Erlang tem uma sintaxe declarativa
• MAS NÃO É PROLOG :)◦ Não há backtracking◦ Todas as variáveis passadas a uma função devem estar
instanciadas◦ Uma função devolve sempre um valor
Erlang – p. 5
Tipos de dados
• Números - inteiros e vírgula flutuante
• Átomos• Tuplos• Listas• Records• Pids (Process Identifier)• Ports• Referências• Binários
Erlang – p. 6
Numeros
• Inteiros
◦ 234◦ 16#ab10f◦ 2#11010101011◦ $A◦ Base#Valor representa um dado valor numa dada
base◦ $Char representa o valor Ascii do caracter
• Vírgula flutuante◦ 45.543◦ 12.34E-10
Erlang – p. 7
Atomos
• São constantes literais• O seu valor é o próprio átomo• Começam com uma letra minúscula• Entre plicas podem conter qualquer caracter• Fora de plicas usar apenas letras “normais”, dígitos e
underscore• Exemplos
◦ abcef23◦ comecam_com_uma_letra_minuscula◦ ’podem ter espaços e outros caracteresdentro de plicas’
Erlang – p. 8
Tuplos
• Agrupar um número fixo de elementos• Sem tamanho máximo para número de elementos ou níveis• Exemplos
◦ {x,’elemento 2’}◦ {a, b,{c,d,[1,2,3,4]},{e,[{x,y,z},f,g]}}
• Funções auxiliares◦ element(N,T) devolve elemento na posição N
• element(2,{a,b,c})→b◦ setelement(N,T,V) atribui a elemento na posição N
valor V• setelement(2,{a,b,c},x)→{a,x,c}
Erlang – p. 9
Listas
• Agrupar um número variável de elementos• Número de elementos constitui o comprimento da lista• Cabeça e cauda ( [H|T])• Exemplos
◦ []◦ [1|[]] → [1]◦ [1,2,3]◦ [1|[2|[3|[]]]] → [1,2,3]◦ [[1,2,3]|[4,5,6]] → [[1,2,3],4,5,6]
Erlang – p. 10
Variaveis
• Usadas para guardar termos Erlang• Uma vez instanciadas não podem mudar o seu valor• Começam por letra maiúscula• underscore pode tomar qualquer valor• Não é necessário declarar variáveis• Exemplos
◦ UmaVariavel◦ Outra_variavel
Erlang – p. 11
Pattern matching
• Atribuição◦ A=2
• Extracção de dados◦ {Nome,Conteudo} = {lista,[1,2,3]}
• Teste◦ Valor = 1, {Valor,X} = {Y,termo_erlang}◦ {A,B,C} = {1,2,3} (sucesso: A=1,B=2,C=3)◦ {A,A,C} = {1,2,3} (falha:A=1!)
Erlang – p. 12
Funcoes
• Cabeça◦ Nome da função◦ Número variável de parâmetros (pode não ter
argumentos)• Corpo
◦ Código a executar• Terminador
◦ Ponto final• Exemplo
soma(Op1, Op2) ->Op1 + Op2.
Erlang – p. 13
Funcoes
• Usada sempre que chamada pelo seu nome e número deparâmetros (aridade)
vezes(X,N) ->X * N.
dobro(X) ->vezes(2,X).
• Mesmo nome mas aridade diferente → funções diferentes!• Devolvem valor determinado pela última acção• Memória é alocada e libertada automaticamente• Todos os parâmetros devem ser conhecidos quando a
função é chamada
Erlang – p. 14
Funcoes com n clausulas
func(Padrao1,Padrao2,...,PadraoN) ->instrucao1,...,instrucaoN;
func(Padrao1,Padrao2,...,PadraoN) ->instrucao1,...,instrucaoN.
• As cláusulas são pesquisadas sequencialmente• Quando é encontrado o padrão correcto todas as variáveis
ficam instanciadas• As variáveis são locais a cada cláusula
Erlang – p. 15
Modulos
• Funções são agrupadas em módulos• Ficheiro deve ter o mesmo nome do módulo (teste.erl)
-module(teste).-export([dobro/1]).vezes(X,N) ->
X * N.dobro(X) ->
vezes(2,X).
• dobro/1 pode ser chamada de fora do módulo• vezes/2 é local ao módulo
Erlang – p. 16
Modulos
• Funções identificadas por módulo, nome e aridade
teste:dobro(5).
• Uma função tem que ser exportada para ser visível fora domódulo
• Dentro do mesmo módulo pode ser omitido nome domódulo◦ Se for usado tem significado especial: permite a
substituição do código em run time
Erlang – p. 17
Recursividade
• Se o valor de uma variável não pode ser alterado depois deter sido atribuído, como podemos fazer iterações?
• Usando recursividade
for(N) -> for(0) ->
for(1,N). ok;
for(N,N) -> for(N) ->
ok; for(N-1).
for(N,Max) ->
for(N+1,Max).
Erlang – p. 18
Recursividade
• A recursividade é muito comum em listas
media(L) ->soma(L) / comprimento(L).
soma([]) ->0;
soma([H|T]) ->H + soma(T).
comprimento([]) ->0;
comprimento([_|T]) ->1 + comprimento(T).
Erlang – p. 19
Recursividade
• Mais padrões comuns
dobro([]) ->[];
dobro([H|T]) ->[2*H|dobro(T)].
membro(X,[X|T]]) ->true;
membro(X,[H|T]) ->membro(X,T);
membro(X,[]) ->false.
Erlang – p. 20
Recursividade
• Usando acumulador
soma(L) ->soma(L,0).
soma([H|T],Soma) ->soma(T,Soma + H);
soma([],Soma) ->Soma.
• Esta versão executa num espaço constante de memória!◦ Memória e velocidade do programa◦ Last call optimization
Erlang – p. 21
Recursividade
• Mais alguns exemplos
comprimento(L) ->comprimento(L,0).
comprimento([H|T],C) ->comprimento(T,C + 1);
comprimento([],C) ->C.
media(L) ->media(L,0,0).
media([H|T],S,C) ->media(T,S + H,C + 1);
media([],S,C) ->S / C.
Erlang – p. 22
Guards
• Condições que têm de ser satisfeitas antes de umacláusula ser escolhida
• Extensão do pattern matching• Apenas um teste ou uma sequência de testes
◦ separados por vírgulas (operador lógico and)◦ pontos e vírgulas (operador lógico or)
• Funções definidas pelo programador não podem serusadas como guards
• when introduz um guard
factorial(1) ->1;
factorial(N) when N > 1 ->N * factorial(N - 1).
Erlang – p. 23
Guards
• Todas as variáveis usadas num guard devem estarinstanciadas
• As cláusulas protegidas com guards podem serreordenadas
factorial(1) ->1;
factorial(N) when N > 1 ->N * factorial(N - 1).
◦ o mesmo que
factorial(N) when N > 1 ->N * factorial(N - 1);
factorial(1) ->1.
Erlang – p. 24
Guards
• Sem guards a ordem das cláusulas não pode ser trocada
factorial(N) ->N * factorial(N - 1);
factorial(1) ->1.
• Exemplos de guardsis_atom/1 is_binary/1 is_list/1
is_float/1 is_integer/1 is_number/1
is_pid/1 is_reference/1 is_record/1
length(List) size(Tuple) X > Y + Z
X == Y element(N,Tuple) hd(List)
Erlang – p. 25
Built-in Functions (BIFs)
• Funções do módulo erlang• Funcionalidades difíceis (ou ineficientes) de conseguir em
Erlang• São as únicas funções que podem ser usadas como guards• Exemplos
trunc(5.6) → 5round(5.6) → 6length([a,b,c,d]) → 4element(2,{a,b,c}) → bfloat(5) → 5.00000is_atom(hello) → truedate() → {2005,02,18}
Erlang – p. 26
Records
• Armazenar um número fixo de elementos• Tuplos apenas acedem aos elementos pela sua posição
◦ Alteração da ordem, remoção ou adição de elementosimplica alteração do programa!
• Records permitem aceder aos elementos pelo seu nome◦ Podemos ignorar a sua ordem
• Não são um tipo de dados nativo◦ São traduzidos para tuplos pelo compilador
Erlang – p. 27
Declaracao de um record
-record(nome_record,{campo1 [=Valor1],...,campoN [=ValorN]})
• Nome do record e dos campos deve ser um átomo• Pode ser dado um valor por omissão a cada campo
◦ Se não for especificado campo assume undefined
• Deve ser declarado antes do seu uso numa função• Exemplo
-record{pessoa,{nome, instituicao=’ISEP’, telefone})
Erlang – p. 28
Criar uma instancia de um record
#nome_record{ campo_1 = Valor1,..., campo_n = Valor_N}
• Os campos podem ser especificados em qualquer ordem• Podem ser omitidos campos
◦ É-lhes atribuído valor por omissão• Exemplo
P = #pessoa{nome=’Joao’}
{pessoa, ’Joao’, ’ISEP’, undefined}
Erlang – p. 29
Aceder a um campo de um record
Record#nome_record.Campo
• Retorna o valor do campo indicado• Record deve ser uma variável do tipo record• Posição do campo pode ser obtida
#nome_record.Campo
• Exemplo
Nome = P#pessoa.nome
Nome → ’Joao’
Erlang – p. 30
Actualizar um record
Novo = Record#nome_record{campo_i = Valor, ...}
• Retorna uma cópia do record com os valores alterados• Record deve ser uma variável do tipo record• Exemplo
P2 = P#pessoa{telefone=12345679}
P2 → {pessoa,’Joao’,ISEP’,123456789}
Erlang – p. 31
Records em guards
• Aceder aos valores dos campos nos guards◦ Exemplo
handle(Msg,State) whenState#state.running == true ->
• BIF is_record(Term, RecordType)◦ Permite determinar tipo do record◦ Exemplo
is_person(P) when is_record(P, pessoa) ->true;
is_person(_P) ->false.
Erlang – p. 32
Records
• Records usados em vários módulos devem ser definidosnum ficheiro .hrl
• Módulos acedem à sua definição com
-include(ficheiro.hrl)
• Durante a compilação é adicionada informação sobre osrecords◦ record_info(fields,Record) devolve lista dos
campos presentes em Record◦ record_info(size,Record) devolve tamanho do
record Record
Erlang – p. 33
Compreensao de listas
• Notação sucinta para gerar elementos de uma lista• “Set Compreension” na teoria dos conjuntos de
Zermelo-Frankel• Similares ao setof e findall do Prolog
[Expr || Condicao1, ..., CondicaoN]
• Expr é aplicado a todos os elementos da lista• Condicao é um gerador ou um filtro
◦ Gerador: Padrao <- ListaTermos◦ Filtro: qualquer expressão que retorne true ou false
Erlang – p. 34
Compreensao de listas
[X||X<-Lista, Condicao1, ..., CondicaoN]
• Lê-se X tal que X pertence a Lista e Condição1, ...• Resultado é uma nova lista com os elementos de Lista
que respeitam as condições• Exemplo
L = [X||X<-[1,2,a,3,4,b,5,6], X>3]
L → [a,4,b,5,6]• Podemos adicionar mais filtros
L = [X||X<-[1,2,a,3,4,b,5,6], X>3, is_integer(X)]
L → [4,5,6]
Erlang – p. 35
Compreensao de listas - Regras
• Variáveis usadas num gerador devem ser “novas”• Variáveis instanciadas antes da compreensão de listas
usadas como filtros mantêm o seu valor• Não é possível exportar nenhuma variável
• Exemplo
select(X,L) -> [Y||{X,Y} <- L]
◦ Objectivo: Construir uma lista com os elementos emque X é o primeiro elemento do tuplo
◦ Resultado ao compilar:Warning: Variable ’X’ shadowed in generate
◦ Problema: X no gerador não é o mesmo X que nocabeçalho da função!
Erlang – p. 36
Compreensao de listas - Regras
• Resultado:
L = select(b,[{a,1},{b,2},{c,3},{b,4}])
L → [1,2,3,4]• Gerador deve conter variáveis não instanciadas• Teste deve ser feito no filtro
select(X,L) -> [Y||{X1,Y} <- L,X1==X]
L = select(b,[{a,1},{b,2},{c,3},{b,4}])
L → [2,4]
Erlang – p. 37
Compreensao de listas - mais exemplos
• Combinar geradores para obter produto cartesiano de duaslistas
L = [{X,Y}||X <- [1,2,3], Y <- [a,b]]
L → [{1,a},{1,b},{2,a},{2,b},{3,a},{3,c}]• Concatenar duas listas
L = [1,2,3] ++ [4,5,6]
L → [1,2,3,4,5,6]• Subtracção de listas
L = [1,2,3,4,1] -- [1,4]
L → [2,3,1]◦ Retira apenas a primeira ocorrência de cada elemento
da 2a lista
Erlang – p. 38
Top Related