Entender Programação Funcional é uma tarefa bem complicada no começo, por ser uma mudança extremamente radical na forma de pensar e de programar.
Na minha opinião temos dois pontos fundamentais a considerar: Listas e Funções. Exceto por modificadores de leitura, tudo ou é um ou é outro, e depende de ambos. Claro que há muito mais, mas acho esse o básico para ao menos “Ler” algo funcional.
Uma Lista não é um Array( ou Vetor) como estamos acostumados, mas uma série encadeada de símbolos(que podem ser ou não outra lista ou função). Para construir a seguinte lista : "Maça, Banana, Laranja" é entendida em idiomas LISP assim: (Maçã Banana Laranja).
Para entender um lista encadeada, podemos ter algo assim: (Maçã ("Banana nanica" "Banana D'Água") Laranja). É uma lista de 3 elementos, sendo que o segundo elemento é uma lista de dois elementos, mas se for assim (Maçã (Banana nanica Banana D'Água) laranja) o segundo elemento tem 4 elementos.
O processamento de Listas (LISP é isso) é feito da seguinte forma, supondo a lista:
(somar 1 2 (dividir 6 3))
O primeiro elemento de uma lista é esperado uma função, os elementos seguintes serão seus parâmetros, então temos a função "somar" recebendo os parâmetros inteiros 1 e 2, e como terceiro parâmetro vai receber o resultado do processamento da lista (dividir 6 3), que vai ser processada como uma chamada a função "dividir" recebendo 6 e 3 como parâmetros, o resultado volta como terceiro parâmetro a somar.
Como podemos ter quase qualquer coisa como símbolos, essa linha é implementada assim:
(+ 1 2 (/ 6 3))
"+" é um simbolo comum, que contem(aponta, na verdade) uma função capaz de somar que receber n argumentos, assim como "/" contem a função de divisão. Toda Lista é processada dessa forma, função + argumentos, apesar de termos modificadores (como # ou ') que alteram esse comportamento. Um array por exemplo é feito dessa forma: [ x y z ], logo não é um lista.
Agora chegamos nas funções, são exatamente como as funções matemáticas. Em LISP se define uma função usando a função especial “defun”, aqui vou usar o idioma de Clojure para demonstrar isto. Em clojure temos:
(defn funcao [x] ( processa x ) )
E o que isso quer dizer? Chamo a função “defn” e passo como argumentos o simbolo “funcao”, o array [x] e a lista ( processa x). “defn” vai ligar ao simbolo de escopo local “funcao” uma função que recebe um argumento ([x]) que será ligado a variável “x” do escopo interno da função, e que vai retornar o resultado da lista (processa x).
Como defn é uma função especial, (processa x) não é processado imediatamente, e sim, apenas quando a função for chamada. Assim quando eu chamo (funcao 3) esta lista vai retornar o resultado de (processa 3). Em um exemplo mais prático, temos:
(defn hello [name] ( println “Hello ” name) )
(hello “Diogo”) ; imprime “Hello Diogo”
(hello “Você”) ; imprime “Hello Você”
Este poderia ser implementado assim:
( (fn [name] (println “Hello ” name)) “Diogo” )
Definindo a função na hora, e passando o argumento. Então por exemplo podemos encadear chamadas:
(defn hello-maker [name] (str “Hello ” name)) ; retorna (str “Hello “ name), str constroi a String
(defn speaker [toSpeak] (println toSpeak))
(speaker (hello-maker “Diogo”))
(defn quick-speak [speaker maker name] ( speaker (maker name))) ; são simbolo, e dentro de um escopo
(quick-speak speaker maker “diogo”)
Lembrando que por padrão somente o primeiro item é interpretado como função, a estrutura acima funciona. Agora um exemplo mais legal, fatorial, formatado:
(defn fac [x] (
if (= x 1)
x
(* x (fac (- x 1)))
)
)
Aqui temos uma séries de funções, a função ligada ao simbolo “=” recebe dois argumentos e retorna verdadeiro (booleano mesmo) se forem, quem diria, iguais. A função “if” (também é especial) recebe tres argumentos: Um boleano, uma lista(ou simbolo) para retornar em caso verdadeiro e uma para retorna caso falso. Ambas não são processadas até que if seja resolvido.
Então ao chamar (fac 5) temos x = 5, se a função “=” resolver que x e 1 são iguais, fac vai retorna x, se não vai retornar uma lista (* x (fac (- x 1))).
Então temos para retorna a função “*” que recebe x e (fac (- x 1)), processando temos fac recebendo (- x 1), que é a função “-” rebendo x e 1 , e vai retornar(surpresa) x - 1 , então retorna fac 4 (que vai ser 4 vezes factorial de 3), e por ai vai.
No caso do (fac 5) temos, no final:
(* 5 (* 4 (* 3 (* 2 1))))
(* 5 (* 4 (* 3 (2))))
até
120
Então:
(defn fac [x] ( if (= x 1) x (* x (fac (- x 1)))))
(println (fac 5)) ; imprime 120
Como disse, isso é o básico do básico, programação funcional é algo bem complexo e há muito a se aprender ainda, mas é divertido e vale a pena. Ainda bem que não sou professor, por me perdi completamente explicando ;)






