Você está na página 1de 37

FUNDAMENTOS DE

PROGRAMAÇÃO FUNCIONAL

Prof. Ricardo P. Mesquita1


INTRODUÇÃO

• O alto grau de similaridade entre as linguagens imperativas surge em parte de uma


das bases comuns de seu projeto: a arquitetura de von Neumann,
• As linguagens imperativas podem ser compreendidas coletivamente como uma
progressão de desenvolvimentos realizados para melhorar o modelo básico,
Fortran I.
• Todas foram projetadas para usar eficientemente a arquitetura de computadores de
von Neumann.
• Apesar de o estilo imperativo de programação ser considerado aceitável pela
maioria dos programadores, sua forte dependência da arquitetura subjacente é vista
por alguns como uma restrição desnecessária nas estratégias alternativas de
desenvolvimento de software.

2
INTRODUÇÃO

• O paradigma de programação funcional, baseado em funções matemáticas, é a


base de projeto dos estilos de linguagem não imperativos mais importantes.
• Em sua palestra, Backus (1978) argumentou que linguagens de programação
puramente funcionais são melhores que linguagens imperativas porque
resultam em programas mais legíveis, mais confiáveis e mais propensos a serem
corretos.
• O cerne de seu argumento é que os programas puramente funcionais são mais
fáceis de entender, tanto durante quanto após o desenvolvimento, em grande
parte porque os significados das expressões são independentes de seu
contexto (uma característica de uma linguagem de programação funcional pura
é que nem expressões nem funções têm efeitos colaterais).

3
INTRODUÇÃO

• Alguns cientistas da computação bastante conhecidos têm tentado promover a


noção de que as linguagens de programação funcional são superiores às linguagens
imperativas tradicionais.
• Lisp começou como uma linguagem funcional pura, mas rapidamente adquiriu
alguns recursos imperativos importantes que aumentaram sua eficiência de
execução.
• Ela ainda é a mais importante das linguagens funcionais, ao menos no sentido de ser
a única a atingir uso disseminado.
• A linguagem é a predominante nas áreas de representação de conhecimento,
aprendizagem automática, sistemas de treinamento inteligentes e modelagem de
fala.

4
INTRODUÇÃO

• O desenvolvimento de linguagens de programação funcional tipadas,


principalmente ML, Haskell, OCaml e F#, levou a uma expansão significativa das
áreas da computação nas quais agora são usadas linguagens funcionais.
• À medida que essas linguagens são atualizadas, seu uso prático aumenta.
• Atualmente, são utilizadas em áreas como processamento de bancos de dados,
modelagem financeira, análise estatística e bioinformática.

5
FUNÇÕES MATEMÁTICAS

• Uma função matemática é um mapeamento de membros de um conjunto,


chamado de conjunto domínio, para outro, chamado de conjunto imagem.
• Uma definição de função especifica, explícita ou implicitamente, os conjuntos
domínio e imagem junto com o mapeamento.

6
FUNÇÕES MATEMÁTICAS

• Uma das características fundamentais das funções matemáticas é que a ordem de


avaliação de suas expressões de mapeamento é controlada por recursão e por
expressões condicionais, não por sequência e repetição iterativa, comuns nos
programas escritos nas linguagens de programação imperativas.
• Outra característica importante delas é que, como não possuem efeitos colaterais
e não podem depender de valores externos, sempre mapeiam um elemento
específico do domínio no mesmo elemento da imagem.
• Contudo, um subprograma em uma linguagem imperativa pode depender dos
valores atuais de diversas variáveis não locais ou globais.
• Isso torna difícil determinar estaticamente os valores que o subprograma produzirá e os
efeitos colaterais que terá em determinada execução.

7
FUNÇÕES MATEMÁTICAS

• Definições de funções são geralmente escritas como um nome de função,


seguido de uma lista de parâmetros entre parênteses, seguidos pela expressão
de mapeamento.
• Por exemplo, cube(x) ≡ x * x * x, onde x é um número real.
• Nessa definição, os conjuntos domínio e imagem são os números reais.
• O símbolo ≡ é usado para significar “é definido como”.
• O parâmetro x pode representar qualquer membro do conjunto domínio, mas
é fixado para representar um elemento específico durante a avaliação da
expressão da função. Essa é uma das maneiras pelas quais os parâmetros das
funções matemáticas diferem das variáveis em linguagens imperativas.

8
FUNÇÕES MATEMÁTICAS

• Os primeiros trabalhos teóricos acerca de funções separaram a tarefa de


defini-las da de nomeá-las.
• A notação lambda, definida por Alonzo Church (1941), fornece um método
para definir funções não nomeadas.
• Uma expressão lambda especifica os parâmetros e o mapeamento de uma
função.
• Ela é a função propriamente dita, que é não nomeada.

9
FUNÇÕES MATEMÁTICAS

• Por exemplo, considere a seguinte expressão lambda:


(x)x * x * x
• Church definiu um modelo de computação formal (um sistema formal para
definição de funções, aplicação de funções e recursão) usando expressões
lambda.
• Ele se chama cálculo lambda, que pode ser tipado ou não tipado.
• O cálculo lambda não tipado serve de inspiração para as linguagens de
programação funcionais.

10
FUNÇÕES MATEMÁTICAS

• Conforme dito anteriormente, antes da avaliação, um parâmetro representa


qualquer membro do conjunto domínio, mas durante a avaliação ele é vinculado a
um membro específico.
• Quando uma expressão lambda é avaliada para um parâmetro, diz-se que ela é
aplicada a esse parâmetro.
• A mecânica de tal aplicação é a mesma para qualquer avaliação de função.
• A aplicação da expressão lambda do exemplo é denotada como a seguir:
• ((x)x * x * x)(2) que resulta no valor 8.
• Expressões lambda, como outras definições de função, podem ter mais de um
parâmetro.

11
FORMAS FUNCIONAIS

• Uma função de ordem superior, ou forma funcional, é aquela que recebe


uma ou mais funções como parâmetros, ou que leva a uma função como
resultado, ou ambos.
• Um tipo comum de forma funcional é a composição funcional, que tem dois
parâmetros funcionais e leva a uma função cujo valor é o primeiro parâmetro
de função real aplicado ao resultado do segundo.
h≡f°g

12
FORMAS FUNCIONAIS

• Aplicar-para-todos (apply-to-all) é uma forma funcional que recebe uma única


função como parâmetro.
• Se usada em uma lista de parâmetros, aplicar-para-todos aplica seu parâmetro
funcional a cada um dos valores na lista de parâmetros e coleta os resultados
em uma lista ou em uma sequência.
• Aplicar-para-todos é denotada por . Seja h(x) ≡ x*x então α(h,(2,3,4)) resulta
em (4, 9, 16).

13
FUNDAMENTOS DAS LP FUNCIONAIS

• O objetivo do projeto de uma linguagem de programação funcional é imitar as


funções matemáticas ao máximo possível. Isso resulta em uma estratégia para a
solução de problemas fundamentalmente diferente das usadas com linguagens
imperativas.
• Em uma linguagem imperativa, uma expressão é avaliada e o resultado é
armazenado em uma posição de memória, representada como uma variável em
um programa.
• Essa é a finalidade das sentenças de atribuição. Essa atenção necessária às
células da memória, cujos valores representam o estado do programa, resulta
em uma metodologia de programação de nível relativamente baixo.

14
FUNDAMENTOS DAS LP FUNCIONAIS

• Um programa em uma linguagem de montagem geralmente também armazena


os resultados de avaliações parciais de expressões.
• Por exemplo, para avaliar (x + y)/(a – b) o valor de (x + y) é calculado
primeiro.
• Esse valor deve então ser armazenado enquanto (a – b) é avaliada.
• Em linguagens de alto nível, o compilador manipula o armazenamento dos
resultados intermediários de avaliações de expressões.
• O armazenamento de resultados intermediários ainda é necessário, mas os
detalhes não podem ser vistos pelo programador.

15
FUNDAMENTOS DAS LP FUNCIONAIS

• Uma linguagem de programação puramente funcional não usa variáveis nem


sentenças de atribuição, liberando o programador de preocupações
relacionadas às células de memória, ou ao estado, do programa.
• Sem variáveis, as construções de iteração não são possíveis, já que são
controladas por variáveis. As repetições devem ser especificadas com recursão,
e não com iteração.
• Os programas são definições de funções e especificações de aplicações de
funções, e as execuções consistem em avaliar a aplicação de funções.
• Sem variáveis, a execução de um programa puramente funcional não tem
estado, no sentido de semântica operacional e denotacional.

16
FUNDAMENTOS DAS LP FUNCIONAIS

• Uma linguagem funcional fornece um conjunto de funções primitivas, um


conjunto de formas funcionais para construir funções complexas a partir
dessas funções primitivas, uma operação de aplicação de função e alguma
estrutura ou estruturas para representar dados.
• Essas estruturas são usadas para representar os parâmetros e os valores
computados pelas funções.
• Se uma linguagem funcional é bem projetada, ela requer apenas um número
relativamente pequeno de funções primitivas.

17
LINGUAGEM FUNCIONAL: LISP

• Com exceção da primeira versão, todos os dialetos de Lisp incluem recursos


imperativos, como variáveis no estilo imperativo, sentenças de atribuição e
iteração.
• Variáveis no estilo imperativo são usadas para nomear células de memória, cujos
valores podem ser modificados muitas vezes durante a execução de um programa.
• Tipos de dados: átomos e listas

18
LINGUAGEM FUNCIONAL: LISP

• As listas são especificadas em Lisp ao delimitarmos seus elementos com


parênteses. Os elementos de listas simples são restritos aos átomos, como em
(A B C D)
• Estruturas de lista aninhadas também são especificadas com parênteses. Por
exemplo,
(A (B C) D (E (F G)))

19
LINGUAGEM FUNCIONAL: LISP

• Representação interna

20
LINGUAGEM FUNCIONAL: LISP

• Representação interna

21
LINGUAGEM FUNCIONAL: SCHEME

• A linguagem Scheme, um dialeto de Lisp, foi desenvolvida no MIT em meados


dos anos 1970
• Ela é caracterizada por ser pequena, ter uso exclusivo de escopo estático e
tratamento de funções como entidades de primeira classe.
• Como entidades de primeira classe, as funções Scheme podem ser os valores
de expressões, elementos de listas, passadas como parâmetros e retornadas de
funções.
• As primeiras versões de Lisp não forneciam todas essas capacidades.

22
LINGUAGEM FUNCIONAL: SCHEME

• Um interpretador Scheme no modo interativo é um laço infinito de leitura-


avaliação-impressão (muitas vezes abreviado como REPL - read-evaluate-print
loop).
• Ele repetidamente lê uma expressão digitada pelo usuário (na forma de uma
lista), interpreta a expressão e mostra o valor resultante.
• Essa forma de interpretador também é usada por Ruby e Python.

23
LINGUAGEM FUNCIONAL: SCHEME

• Exemplo:

24
LINGUAGEM FUNCIONAL: SCHEME

• Em Scheme, uma função não nomeada inclui a palavra LAMBDA e é chamada


de expressão lambda.
• Por exemplo, a seguinte expressão retorna 49:
(LAMBDA (x) (* x x)) 7)
• Nessa expressão, x é chamada de variável vinculada dentro da expressão
lambda. Durante a avaliação dessa expressão, x é vinculada a 7. Uma variável
vinculada nunca muda na expressão após ter sido vinculada a um valor de
parâmetro real no momento em que inicia a avaliação da expressão lambda.

25
LINGUAGEM FUNCIONAL: SCHEME

• Exemplo de código:

26
LINGUAGEM FUNCIONAL:
COMMON LISP

• Common Lisp (Steele, 1990) é o resultado de um esforço para combinar os


recursos de diversos dialetos anteriores de Lisp, incluindo Scheme, em uma
única linguagem.
• Já que consiste em uma espécie de união de linguagens, ela é muito extensa e
complexa; similar, nesse sentido, a C++ e C#.
• Sua base, entretanto, é Lisp original; portanto, sua sintaxe, funções primitivas e
natureza fundamental vêm dessa linguagem.

27
LINGUAGEM FUNCIONAL:
COMMON LISP

• Exemplo: fatorial em Common Lisp

28
LINGUAGEM FUNCIONAL:
COMMON LISP

• A lista de recursos de Common Lisp é longa: um grande número de tipos e


estruturas de dados, incluindo registros, matrizes, números complexos e
cadeias de caracteres; operações de entrada e saída muito eficientes; e uma
forma de pacotes para modular coleções de funções e de dados, e também
para fornecer controle de acesso.
• Common Lisp inclui várias construções imperativas e alguns tipos mutáveis.

29
LINGUAGEM FUNCIONAL:
COMMON LISP

• Reconhecendo a flexibilidade ocasionalmente fornecida pelo escopo dinâmico,


assim como a simplicidade do escopo estático, Common Lisp permite ambos.
• O escopo padrão para variáveis é estático, mas ao se declarar uma variável
como “especial” (special), o escopo dela se torna dinâmico.
• Macros são frequentemente usadas em Common Lisp para estender a
linguagem.

30
LINGUAGEM FUNCIONAL: ML

• ML (Milner et al., 1997) é uma linguagem de programação funcional com


escopo estático, como Scheme.
• Entretanto, ela difere de Lisp e de seus dialetos, incluindo Scheme, de diversas
maneiras significativas.
• Uma diferença importante é o fato de ML ser uma linguagem fortemente
tipada, enquanto Scheme é essencialmente desprovida de tipos.
• ML tem declarações de tipo para os parâmetros de função e para os tipos de
retorno de funções, embora muitas vezes não sejam usadas, devido à sua
inferência de tipos.
• O tipo de cada variável e expressão pode ser determinado estaticamente.

31
LINGUAGEM FUNCIONAL: ML

• ML, como outras linguagens de programação funcional, não tem variáveis, no


sentido das linguagens imperativas.
• Ela tem identificadores, os quais têm a aparência de nomes de variáveis das
linguagens imperativas.
• Contudo, é melhor considerar esses identificadores como nomes de valores.
Uma vez definidos, eles não podem ser alterados.
• São como as constantes nomeadas das linguagens imperativas, como
declarações final em Java.
• Os identificadores de ML não têm tipos fixos – qualquer identificador pode ser
o nome de um valor de qualquer tipo.

32
LINGUAGEM FUNCIONAL: ML

• Exemplo: função fatorial

33
LINGUAGEM FUNCIONAL: HASKELL

• Similar a ML por usar uma sintaxe semelhante, ter escopo estático, ser
fortemente tipada e utilizar o mesmo método de inferência.
• Existem três características de Haskell que a diferenciam de ML.
• Primeiro, as funções em Haskell podem ser sobrecarregadas (as funções em
ML, não).
• Segundo, semânticas não estritas são usadas em Haskell, enquanto em ML (e na
maioria das outras linguagens de programação) são usadas semânticas estritas.
• Terceiro, Haskell é uma linguagem de programação funcional pura, ou seja, não
tem expressões nem sentenças com efeitos colaterais, enquanto ML permite
alguns efeitos colaterais (por exemplo, ML tem vetores mutáveis).

34
LINGUAGEM FUNCIONAL: F#

• F# é uma linguagem de programação funcional .NET cujo núcleo é baseado em


OCaml, que é uma descendente de ML e Haskell.
• Embora seja fundamentalmente uma linguagem funcional, ela contém recursos
imperativos e suporta programação orientada a objetos.
• Uma das características mais importantes de F# é o fato de ter um IDE
completo, uma ampla biblioteca de utilitários que suportam programação
imperativa, orientada a objetos e funcional, além de interoperabilidade com
uma coleção de linguagens não funcionais (todas as linguagens .NET).

35
LINGUAGEM FUNCIONAL: F#

• F# é uma linguagem .NET de primeira classe.


• Isso significa que os seus programas podem interagir de todas as maneiras com
outras linguagens .NET.
• Por exemplo, classes F# podem ser usadas e estendidas (por meio de
especialização) por programas em outras linguagens e vice-versa.
• Além disso, os programas F# têm acesso a todas as APIs do Framework .NET.
• A implementação de F# está disponível gratuitamente no site da Microsoft.
• Ela também é suportada pelo Visual Studio.

36
DÚVIDAS?

37

Você também pode gostar