Mais sobre programação funcional e clojure

No último texto tentei explicar o básico para entender um lista em programação funcional, agora vou explicar algumas das estruturas mais essenciais para um programa funcional que seja , bem, funcional.

Vamos começar pela definição de funções, no outro texto expliquei a forma mais simples:

(defn soma [ arg0 arg1 ] ( + arg0 arg1 ) )

Essa é na verdade uma forma especial para a função que cria funções:

(def soma (fn [arg0 arg1] (+ arg0 arg1))

Essa forma original permite a primeira forma de polimorfismo de clojure, por número de argumentos:

(def soma ( fn somador ; somador é um alias opcional que sera usado dentro da funcao
 ( [arg0 arg1 ] (+ arg0 arg1))
 ( [arg0 arg1 arg2] ( somador arg0 (somador arg1 arg2))
))

Algo muito importante em programação funcional é a recursão, usada comumente no lugar de loops tradicionais, que é otimizada por recursos de tail recursion, apesar dessa otimização não ser presente no clojure, a recursividade é essencial, e a forma é com a expressão “recur”:

(defn gimme5 [ x ] 
 ( if (= x 5) 
 x
 ( recur ( + x 1))
))

Veja que vai chamar recur até que x seja igual a 5.

Uma outra forma de implementar funções também muito importante, por ter uma maior capacidade de polimorfismo é com a definição de métodos:

(defmulti hello class)
(defmethod hello String [s] (println “String: “ s))
(defmethod hello Integer [i] (println “Integer:” i))

Mais é possível muito mais que isso, pode mudar a quantidade e tipos de argumentos entre outros.

Uma construção muito importante também é o “let”, ele permite criar um ou mais símbolos e torna-los disponíveis em uma lista, veja:

(let [ x 1 y 2] ( + x y ))
(def hello [name] ( let [ intro “Hello “] (str intro name))
(def n5 (let [ x 1 sum (fn [x y] ( + x y)] (sum 4 x)))

Outra forma importante é a “do”, que executa uma série de funções:

(defn hello [s] (
 let [intro “hello ”]
 do (println “will print hello”) (println intro s) (str intro s)
)); retorna sempre a ultima instrução String de intro + s