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