quinta-feira, fevereiro 19, 2009

O Não Tão Básico do Básico - Paradigmas de Programação - Final

Os paradigmas que vimos nas partes anteriores (Não Estruturado, Estruturado e Orientado a Objeto) são os mais usados anteriormente. O que, nem de longe, significa que são os únicos. Para fechar esta série de posts, vamos ver um destes paradigmas menos usuais, a Programação Funcional.

Programação Imperativa

Os paradigmas anteriores são considerados Imperativos: um programa é composto por comandos que alteram um estado (principalmente variáveis) à medida em que são executados. Um dos comandos básicos destas linguagens é a atribuição, onde um novo valor é atribuído a uma variável. Por exemplo, seguindo aproximadamente a sintaxe do Pascal:
Integer n;

n := 3;
writeln (n);
n := 5;
writeln (n);
Neste trecho a variável n recebe inicialmente o valor 3 e posteriormente o valor 5.

Programação Funcional

Na programação funcional um programa são executados através da resolução de expressões. Expressão, neste contexto, se assemelha mais a uma fórmula matemática (que se aplica a vários valores dos seus parâmetros) do que a uma conta aritmética (que é aplicada a valores específicos).

Na programação funcional as funções são de primeira classe, podendo ser usadas nas mesmas construções que valores. Isto possibilita codificar funções de maior ordem, capazes de receber funções como parâmetros e retornar funções. Na maioria das vezes estas funções são puras, isto é, produzem apenas o seu resultado sem nenhum efeito colateral (inclusive entrada e saída).

No lugar de interação (repetições ou loops), a programação funcional costuma usar recursão.

O resultado é uma forma completamente diferente de se resolver problemas e expressar esta solução. Como exemplo, vamos ver o nosso algoritmo de determinação do maior divisor comum na linguagem Haskell.

Escrever este exemplo foi realmente uma viagem, e só consegui porque achei um exemplo pronto. Vamos ao resultado:
module Main where

mdc :: Integer -> Integer -> Integer
mdc a 0 = a
mdc a b = mdc b (a `rem` b)

main = do putStrLn "a ?"
a <- readLn
putStrLn "b ?"
b <- readLn
putStrLn "mdc(a,b) = "
print (mdc a b)
O que se passa aqui?

O maior divisor comum é definido como uma função que recebe dois inteiros e devolve um terceiro. Se o segundo for zero, o resultado é o primeiro, caso contrário o resultado é o maior divisor comum entre o segundo e o resto da divisão do primeiro pelo segundo. É exatamente o que o nosso algoritmo descreve, porém aqui não temos variáveis, interação e controle de fluxo.

A "função principal" é um pouco mais semelhante ao que fizemos nos outros paradigmas; temos até duas variáveis a e b.

Para quem quiser se aprofundar em Haskell, seguem alguns links:

Homepage do Haskell: http://haskell.org/
Tutorial curto: http://haskell.org/haskellwiki/Learn_Haskell_in_10_minutes
Haskell para quem conhece C: http://www.haskell.org/~pairwise/intro/section1.html
Um interpretador livre para Haskell: http://www.haskell.org/hugs/

Nenhum comentário: