Você está na página 1de 8

apache functor_

APACHE
!"#$%&
Programação Funcional em Java

!"# $%&"'(")*+,-"(."/!012(% 1"1 3"43%&' 3"5106 1&$"%(. 3"&3"2<&.&'&3"X3"E91NO(3"2 . "H&3(K+LC


P dos, havia um grupo de pesquisadores interes-
sados em sistemas formais. Entre eles ilustravam Princípios da programação funcional
1 .(3"2 . "7$&1"89!01:-"; <1"# 1"=(9.&11-">9!%" 7H&0P " 3Q " &J!(3(1%&' 3" &$:913" ' 3" J!012TJ0 3"
?@'($"("7$ 1A "B<9!2<C"43%("D$%0. "E !F 9" "2 12(06 HG302 3"'&"J! :!&.&NQ "E9120 1&$"KYLKZL[
% " '(" 9." 303%(.&" E !.&$" 2<&.&' " 2G$29$ " $&.H'&-" » /! :!&.&NQ "\.J(!&%0#&"#3C"/! :!&.&NQ "](6
cujo nome vem da letra grega "IJ&!&"9."!(39. "EG6 clarativa
cil de ler sobre essa história, veja K)L). » Evitar mutable state
M"2G$29$ "$&.H'&"E 0"2!0&' "J&!&"3("(3%9'&!"J! 6 » ^91NO(3"2 . "U"!3%62$&33"#&$9(3
J!0('&'(3".&%(.G%02&3"'("E91NO(3"2 .J9%&20 1&03C" » Higher-order functions
Ele provê uma semântica simples para modelar sis- » Side-Effect-Free functions
%(.&3"93&1' "E91NO(3C"7"3(:90!-"9."(P(.J$ "'("E916 » Lambdas e Closures
NQ "$&.H'&"R9("!(2(H("9.&"E91NQ "E"("9.&"#&!0G#($"P" » Recursividade
2 . "&!:9.(1% 3"("&J$02&"&"E91NQ "E"(."PC » Lazy vs. Eager Evaluation
!"!#!! !$!#!"!$ » Gluing functions
7"J! :!&.&NQ "E9120 1&$"S"9."2 1F91% "'("J!016 73"$01:9&:(13"'("J! :!&.&NQ "E9120 1&03"2 . "
2TJ0 3"'(U"10' 3"J($ "2G$29$ "$&.H'&-"J($&"%( !0&"' 3" Lisp, Clojure, Ruby, Scala, Haskell etc. não imple-
tipos KVL, teoria da função recursiva e por outros ramos mentam necessariamente, e nem somente, todos os
'&"$W:02&"("'&".&%(.G%02&C"41R9&1% "(." !0(1%&NQ " princípios listados acima. Mas isso não quer dizer
a objetos tem-se um objeto como base para a cons- que uma seja mais funcional que a outra, nem o con-
trução do nosso programa, em programação funcio- %!G!0 C

/ 48
'()*+,-.,/0*+12034,5,6()*+73)809461.:+;
8"0/+3"%#"%9+1:&#;!&-%&#(&#<&!0"%3&%$"6 =+0&-%$>1!"%3&%*/+%&/.0&$+%3&%1"#$*) "0&$%!#3&.&#3&# &$%&%*/%3"$%6*#3+3"0&$%3+%?*7
.!@+A$%B%< .CDD===E *.!)+A$E1"/%B%F*# +/&# &%1"/%GH$+0%8&0#+#3&$%B%< .CDD===E1&$!#<+E1"/E%IJ%.+)&$ 0+$%&%&$10&,&%+0 !("$%#"%
K0+$!)%&%#"%&L &0!"0-%H%/"3&0+3"0%3"%6>0*/%3&%?"")$%M%?&1<#!N*&$%3"%O* "/+ &3%?&$ !#(%P#$ ! * &%&%/&/A0"%+ !,"%3&%.0"F& "$%Q.&#%
R"*01&E%S"% &/."%)!,0&-%.0+ !1+%&$1+)+3+-%$)+1:%)!#&-%$*06+-%1"00&%&%3&$&#<+E%T"1U%."3&%&#1"# 0+0%/+!$%$"A0&%&)&%#"%$&*%$! &%%B%< .CDD
===E:!#"$<! +E& !EA0E

Apesar de ter sido criada há décadas, a programação funcional


ganhou mais força recentemente com linguagens funcionais como
Scala e Clojure. Lambdas, parte da programação funcional, tam-
bém já estão previstos para o Java 8, e APIs, como Apache Collec-
!"#$%&%'""()&%'*+,+-%."$$*&/%.0!#12.!"$%3+%.0"(0+/+45"%6*#1!"7
nal em algumas classes e em alguns métodos. Neste artigo, é feita
uma introdução à programação funcional em Java usando o Apache
Functor.

Programação Imperativa vs. Evitar mutable state


Programação Declarativa Programas que utilizam programação funcional
Programação declarativa e programação 1 !.&$.(1%(" 1Q " 9%0$0A&." .9%&H$(" '&%&C" \33 " R9(!"
imperativa são dois paradigmas de computação. Na dizer que quando criamos uma função, muitas vezes
programação imperativa, dizemos ao compilador o os valores que passamos não são alterados ou, quan-
que queremos, passo a passo. do são alterados, isso é feito através de recursivida-
de.
Listagem 1. Exemplo de programação imperativa. Desta maneira, não precisamos nos preocupar
com uma função tendo um dos seus valores altera-
for( int i = 0 ; i <= 10 ; ++i ) {
dos por outros objetos, threads ou internamente.
if( i % 2 == 0 ) {
System.out.println(i + “ is even”); \33 " J(!.0%(" R9(" J! :!&.&3" R9(" 9%0$0A&." J! 6
}
} <)49,4,=0>?(?*@4,?*3(?,);4,A-B,?,);,
framework?
_9&$" &" '0E(!(1N&" (1%!(" 9.&" 7/\" (" 9." E!&6
;G"2 ."J! :!&.&NQ "'(2$&!&%0#&-"'&. 3"9.&"!(6 mework?
gra, uma declaração de como queremos que o pro- ` 2a"J! #&#($.(1%("(12 1%!&!G".90%&3"'(U"106
grama se comporte. NO(3"(3J&$<&'&3"(."$0#! 3-"&!%0: 3"("b(H30%(3"J&!&"
7/\"("E!&.(b !cC"_9&1' "(3%9'&#&"1 "d&2c(1A0(-"
Listagem 2. Exemplo de programação declarativa. tive a chance de conhecer muita gente interessan-
%(-" 9.&" '($&3-" ^(!1&1' " ?&!20&" I 9" 80 AQ e" '(9"
UnaryPredicate<Integer> isEven = new
9.&"(PJ$02&NQ "R9(":9&!' "&%S"< F(C
UnaryPredicate<Integer>() {
public boolean test(Integer number) { ](0P&1' " '(" $&' " &3" '(U"10NO(3" H(." E !.&03-"
return number % 2 == 0; ele disse que um framework fazia você escrever
} seu código seguindo as linhas dele, às vezes pre-
}; cisando mudar o jeito como você modela seus ob-
IntegerRange zeroToTen = new IntegerRange(0, 11); F(% 3C"/ !" 9%! "$&' -"9.&"7/\"# 2a"9%0$0A&"1 "3(9"
for(Integer number : zeroToTen.toCollection()) { 2W'0: " J&!&" (P(29%&!" 9.&" E91NQ " (3J(2TU"2&C" 5."
if ( isEven.test(number) ) { E!&.(b !c"%&.HS."'03J 10H0$0A&"9.&"7/\"J&!&" "
System.out.println(number + “ is even”);
.91' "(P%(!1 "J&!&"9%0$0A&NQ C
}
}
M" 7J&2<(" ^912% !" S" 9.&" 7/\" J&!&" ;&#&-" R9("
adiciona suporte a alguns tipos que usamos para
(32!(#(!"2W'0: ".&03"E9120 1&$C"73".9'&1N&3"R9("
você precisa fazer no seu código são resultado da
7"2 .J9%&NQ "E9120 1&$"S"9.&".&1(0!&"'("J! 6
mudança de paradigma de programação orientada
gramar declarativamente.
a objetos e imperativa para uma versão mais fun-
cional.
49 \
:!&.&NQ "E9120 1&$"3(F&.".&03"EG2(03"'("3(!(."93&- (12 1%!&!" 9%! " 1 .(" J&!&" U!3%62$&33" HF(2%3[" U!3%-
dos em ambientes de alta concorrência. Como seus -class citizens.
valores não mudam, se o objeto for acessado por di-
ferentes threads ao mesmo tempo, não corremos o Higher-order functions
risco de trabalharmos com valores desatualizados. Higher-order function é uma função que recebe
M9%!&" #&1%&:(." S" R9(" (33&" J!G%02&" %&.HS." E&- outra função como argumento e/ou retorna uma fun-
cilita a criação de testes de unidade, uma vez que é ção. Por isso o nome que poderia ser traduzido como
.&03"EG20$".&J(&!" "2 .J !%&.(1% "' 3" HF(% 3C E91NQ "'(" !'(.".&0 !C"7".&1(0!&".&03"EG20$"'("2 .-
=&"f03%&:(.")"S"&J!(3(1%&'&"9.&"2$&33("R9("!(- preender isso é lendo código.
presenta um objeto ChangeLogSet vazio no Jenkins
IE !c"' "3(!#0' !"'("01%(:!&NQ "g9'3 1-"&.H 3"2!0&- Listagem 4. Exemplo de higher-order function.
' 3"J !"> <39c(">&b&:92<0eC"_9&1' " "303%(.&"1Q "
(12 1%!&"2<&1:(3"1 "hBd"I:0%-"h`=-"(%2Ce"($("!(% !1&" Integer[] numbers = new Integer[]{3, 2, 4};
Arrays.sort(numbers, new Comparator<Integer>() {
um objeto desse tipo.
public int compare(Integer o1, Integer o2) {
Listagem 3. Exemplo de immutable object. return o1.compareTo(o2);
}
/** });
* {@link ChangeLogSet} that’s empty. System.out.println(Arrays.toString(numbers));
*
* @author Kohsuke Kawaguchi 7"3&T'&"' "2W'0: " &20.&"S"KV-"+-"YLC"B!0&. 3"9."
*/ array de inteiros e, usando o método sort da classe
C*49 class EmptyChangeLogSet extends
!"!#$%&'#())!*+,-.)/01!2.+-!-'&+%!-+03$014&!'201%0#-
ChangeLogSet<ChangeLogSet.Entry> {
/*package*/ D;83E#24*F?G+FH?3(AbstractBuild<?, ?> Porém o que é mais interessante é o segundo argu-
build) { mento que usamos no método sort. Em Java dizemos
super(build); que o segundo argumento é uma classe interna anô-
} nima.
(5.)!- 6./02.+- /&70)- 3$0- .- 28%./.- +.)%- 8- $2!-
@Override 9$1:;.- <3$0- .)/01!- &%01+=- 3$0- )040>0- .$%)!- 9$1:;.-
public boolean 01D;83EH?3() { <3$0-4.26!)!-/.&+-&%01+=,-.$-+0 !,-$2!-?&5?0)-.)/0)-
return true;
function.
}

public Iterator<Entry> iterator() { Side-Effect-Free functions


return Collections.<Entry>?;83EH?3().iterator(); Este princípio garante que uma função retorna
} sempre os mesmos valores quando usamos os mes-
} 2.+-"!'.)0+-/0-01%)!/!#-@2!5&10,-6.)-0A026'.,-$2!-
função que informe a velocidade, dados, o tempo e a
Esse objeto não possui estado. Sempre que você ve-
/&+%B14&!,-.$-!'5.-4.2.C-"0'.4&/!/0-</&+%B14&!,-%02-
!0U2&"3(" "2 1F91% "'(".9'&1N&3"'("9."4.J%iB<&1-
po).
:(f :h(%"(3%G"#&A0 -"($("!(% !1&"%!9(C"](33&".&1(0!&"
você não precisa se preocupar com o estado do obje- Listagem 5. Exemplo de side-effect-free code.
% "I 9" "%&.&1< "'&"$03%&"'("2<&1:(3-"J !"(P(.J$ eC"
protected static BinaryFunction<Double, Double,
Sempre que um objeto do tipo EmptyChangeLogSet
Double> velocity = new BinaryFunction<Double, Double,
vier, você sabe que é um objeto sem changes e que o Double>() {
(3%&' "'($("1Q ".9'&!G"I!(J&!("R9("1Q "<G".S% ' 3" public Double evaluate(Double distance, Double time) {
J&!&". '0U2&!"3(9"(3%&' eC return distance / time;
}
!"#$%&'()*)'+,&-.(/0&&'10/!%&' };
53&!"E91NO(3"2 . "U!3%62$&33"#&$9("30:10U2&-"!(-
39.0'&.(1%(-" R9(" E91NO(3" 3Q " %!&%&'&3" 2 . " U!3%- public static void main(String[] args) {
62$&33" HF(2%3C"M9"3(F&-"# 2a"J '("9%0$0AG6$&3"2 . "9." Double distance = 1000.0; // meters
tipo no seu programa, passando para outros objetos, Double time = 2.0; // seconds
usando para retornar valores, inserindo em estrutu- Double result = velocity.evaluate(distance, time);
System.out.println(result + “ m/s”);
!&"'("'&' 3"("2!0&1' "#&!0G#(03"&J 1%&1' "J&!&"(3%&"
}
função.
4.";&#&-" HF(% 3"("%0J 3"J!0.0%0# 3"3Q "U!3%62$&33" D++!-9$1:;.-)0%.)1!)E-+026)0-.-20+2.-)0+$'%!-
HF(2%3"'&"$01:9&:(.C"= ";&#&"j-"$&.H'&3"%&.HS."3(- /.-<FGG#G-2H+=-+0-".4I-)060%&)-.+-"!'.)0+-/0-01%)!/!-
!Q " U!3%62$&33" HF(2%3C" 4." &$:913" $9:&!(3" # 2a" J '("

/ 50
<JGGG#G-0-K#G=#-D+%0-6)&14L6&.-8-2$&%.-M%&'-3$!1/.-0+- 6&'?!-/0-0A04$:;.,-0-!'5$1+-/!/.+-6./02-+0)-/&+6.-
4)0"02.+-%0+%0+-%!2>82,- E-3$0-1;.-6)04&+!2.+-1.+- nibilizados em um escopo global ou local, através de
preocupar escrevendo diversos testes, uma vez que parâmetros.
o comportamento da função é bem conhecido e sa- `-0A026'.-2!&+-4'E++&4.-/!/.-02-4$)+.+-/0-4.2-
>02.+-3$0-1;.-?E-090&%.+-4.'!%0)!&+#-N!)!-+!>0)-2!&+- putação para recursividade é o de números fatoriais.
sobre o assunto, leia este ótimo artigo OPQ. a02,- "!2.+- "0)- $2!- "0)+;.- 90&%!- 4.2- 6).5)!2!:;.-
funcional e outra feita com programação imperativa.
Listagem 6. Teste de unidade para o código da
R&+%!502-F# Listagem 7. Exemplo de recursividade.
@DataProvider(name=”testData”) public static int factorial( int value ) {
public Object[][] getTestData() { if ( value == 1 ) {
return new Object[][] { return value;
new Object[] {1000.0, 2.0, 500.0}, } else {
new Object[] {500.0, 2.0, 250.0}, return value * factorial((value -1));
new Object[] {3.0, 2.0, 1.5} }
}; }
}
public static UnaryFunction<Integer, Integer> factorial =
@Test(dataProvider=”testData”) new UnaryFunction<Integer, Integer>() {
public void !" #!$%&' ((Double distance, Double time, public Integer evaluate(Integer number) {
Double expectedVelocity) { return number == 1 ? 1 :
Double velocity = (number*evaluate((number-1)));
SideEffectFree1.velocity.evaluate(distance, time); }
Assert.assertEquals(velocity, expectedVelocity); };
}
Recursividade tem um papel importante em pro-
gramação funcional, facilitando que evitemos muta-
Lambdas e Closure ble state e mantenhamos nosso programa mais de-
Lambdas e closures não são suportados em Java clarativo, e menos imperativo. Para ver mais dicas de
!&1/!,-!60+!)-/!-STU-<S!"!-T604&V4!%&.1-U03$0+%=-WWF- como utilizar recursividade corretamente, consulte OXQ
%0)-+&/.-4)&!/!#-(-STU-WWF-0+%E-6)0"&+%!-6!)!-KGJK-4.2- 02-)090)I14&!+,-1.-V1!'-/0+%0-!)%&5.#
.- S!"!- X- 0- 6)0"I-!-4)&!:;.- /0-'!2>/!+-02- S!"!,-4.2-
uma notação semelhante à de C#.
Lambdas são semelhantes às classes internas
anônimas. Podemos usar um lambda para criar uma
função que pode receber parâmetros e retorna, ou
não, um valor. Em algumas linguagens, como Scala,
um lambda pode retornar valores em formato de tu-
plas.
(-+&1%!A0-0+4.'?&/!-6!)!-.-S!"!-X-8-+020'?!1%0-Y-
D++!-&2!502-2.+%)!-!-6&'?!-/0-0A04$:;.-/.-6).-
3$0- E-0A&+%0-02-Z[#-\.-4]/&5.-!>!&A.,-8-!6)0+01%!/.-
grama acima no Eclipse. Repare como o mesmo mé-
$2-0A026'.-O^Q-/0-4.2.-V4!)&!-.-4]/&5._0A026'.-3$0-
todo aparece mais de uma vez.
usamos em higher-order functions com lambdas.
Arrays.sort(numbers, #{ Integer left, Integer right -> Lazy vs. Eager Evaluation
left.compareTo(right) }); b$02- $%&'&7!- (N@+- /0- `Uc- <`> 04%- U0'!%&.1!'-
c!66&15=- E-/0"0-4.1?040)-0+%0+-4.140&%.+#-R!7*-D"!-
Closures são semelhantes aos lambdas, porém '$!%&.1- %!2>82- +$)5&$- 4.2- .- 4E'4$'.- '!2>/!,- 02-
0'0+- $%&'&7!2- "!)&E"0&+- 3$0- 6./02- 0+%!)- 02- $2- 0+- Jd^J-4.2- Z?)&+%.6?0)- N#- e!/+f.)%?#- D2- 0!50)- 0"!-
copo maior. É como quando utilizamos propriedades luation, temos os valores calculados completamente
V1!&+-02-4'!++0+-!1&1?!/!+-02-S!"!# antes de precisarmos destes valores.

Recursividade Listagem 8. Exemplo de eager evaluation.


Em recursividade, uma função chama a si mesma List<Integer> zeroToTenEager =
repetidamente, até atingir uma condição de parada. Arrays.asList(0,1,2,3,4,5,6,7,8,9,10);
No caso de Java, um método chama a si mesmo, pas- // ...
+!1/.-6!)!-+&-.> 0%.+-.$-%&6.+-6)&2&%&".+-<V)+%_4'!++- for( Integer number : zeroToTenEager ) {
objects). Cada chamada gera uma nova entrada na System.out.println(number);
}

51 \
\.- 0A026'.- !1%0)&.),- &26)&2&2.+- .+- 1M20).+- \.- 0A026'.- !1%0)&.),- %02.+- !- 9$1:;.- +.)%,- 3$0-
de zero a dez, utilizando eager evaluation. Repare )040>0-/.&+-!)5$201%.+#-`-6)&20&).-!)5$201%.-8-$2-
que na primeira linha criamos uma lista de inteiros array de inteiros. Podemos dizer que o segundo ar-
de zero a dez. Essa lista é usada em seguida, porém gumento é uma função que compara dois elementos
6./0)&!-+0)-$%&'&7!/!->02-/06.&+-/0-.$%)!+-&1+%)$:g0+- 60)%01401%0+-!.-6)&20&).-!)5$201%.#-`$-!'5.-4.2.-!-
1.- 4]/&5.#- (5.)!- "!2.+- )09!70)- .- 20+2.- 0A026'.- seguinte função.
com lazy evaluation.
sort( array, compareFunction() )
Listagem 9. Exemplo de lazy evaluation.
Dizemos que sort é uma função que recebe outra
IntegerRange zeroToTenLazy = 9$1:;.- i- 4.26!)0j$14%&.1#- (++&2,- +.)%- %02- .)/02-
new IntegerRange(0, 11); // inclusive, exclusive 2!&.)-3$0-4.26!)0j$14%&.1-<"0 !-?&5?0)_.)/0)-9$14-
// ... tion).
for( Integer number : zeroToTenLazy.toCollection() ) {
System.out.println(number);
} Vantagens e desvantagens do uso de
programação funcional
Na lazy evaluation, valores são calculados quan- Programação funcional não é a solução para to-
/.- $2!- 0A6)0++;.- 8- 4?!2!/!,- 2!+- 1;.- !1%0+- 3$0- /.+-.+-4!+.+#-(++&2-4.2.-02-"E)&.+-.$%).+-)!2.+-/0-
isso. Na primeira linha, criamos um Generator que 4.26$%!:;.,-8-1040++E)&.-601+!)->02-!1%0+-/0-!/.%!)-
somente criou os números de zero a dez na segunda qualquer paradigma em um projeto, seja programa-
linha. Dessa maneira implementamos apenas decla- ção funcional, imperativa, orientação a objetos, entre
rativamente nosso conjunto de elementos e, utilizan- outros.
do lazy evaluation, criamos uma estrutura de dados \!- '&+%!- !>!&A.,- +;.- !6)0+01%!/!+- !'5$2!+- "!1-
3$!1/.-0'!-0)!-1040++E)&!#- tagens e desvantagens do uso de programação fun-
Com lazy evaluation, temos a opção de imple- cional.
mentar algumas coisas que seriam mais difíceis com
0!50)-0"!'$!%&.1#-D2-+$!-6!'0+%)!-02-KGJJ-1.-@@-T;.- Vantagens
N!$'.-N0)'-e.)h+?.6,-R!))*-e!''-2.+%).$-!'5$1+-/.+- » Z]/&5.-2!&+-9E4&'-/0-01%01/0)#-
1.".+- )04$)+.+- /.- N0)'- P#- D1%)0- !+- 1."&/!/0+,- 0++!- » c!&+-9E4&'-/0-0+4)0"0)-4]/&5.-4.14.))01%0#-N)&1-
1."!- "0)+;.- &26'0201%!)E- !'5$1+- )04$)+.+- /0- 6).- cipalmente por evitarmos mutable state.
gramação funcional, incluindo lazy evaluation. Com » c./$'!)&/!/0#- (%)!"8+- /0- ?&5?0)_.)/0)- 9$14-
&++.,-02-N0)'-+0)E-6.++L"0'-4.1+%)$&)-$2!-'&+%!-/0-1M- %&.1+- 4.1+05$&2.+- 4.2>&1!)- /&"0)+!+- 9$1:g0+-
20).+-/.-70).-!.-&1V1&%.#-@2!5&10-9!70)-&++.-4.2-0!- 02-$2!-1."!-0-4)&!)-2]/$'.+-)0$%&'&7E"0&+#
ger evaluation. » c!&+-9E4&'-%0+%!)#
!"#$%&%$'()%* +(,-"."/001%23"
Desvantagens
» Pode ser mais difícil de depurar, dependendo
/!-@kD,-(N@,-01%)0-.$%).+-9!%.)0+#
Gluing functions » Paradigma diferente para muitos programado-
Linguagens de programação funcional são base- )0+,-6.)%!1%.-?E-$2!-4$)"!-/0-!6)01/&7!/.#
adas em chamadas estruturadas a uma função. Um » (60+!)-/0-0A&+%&)02-(N@+-02-S!"!-6!)!-6).5)!-
programa funcional é uma função que chama outras 2!:;.-9$14&.1!'-<l$!"!,-9$1m ,-9$14%&.1!' !"!,-
9$1:g0+- OWQ#- `- 1.20- /!/.- !- 0++0- 014!/0!201%.- /0- '!2>/! ,-.6m ,-(6!4?0-j$14%.)=-0'!+-.$-1;.-+;.-
9$1:g0+,-5'$&15-9$14%&.1+,-8-$2-/.+-1.20+-60'.-3$!'- maduras ou possuem pouca documentação e
você pode encontrar mais sobre esse assunto, outros !&1/!-1;.-V)2!)!2-$2!-4.2$1&/!/0-!.-)0/.)#
nomes são: composition e nesting. É importante ressaltar que tanto vantagens como
N./02.+- $+!)- .- 0A026'.- !6)0+01%!/.- !3$&- 02- desvantagens podem variar dependendo do progra-
higher-order functions. ma e do programador. É possível que um código seja
escrito com programação funcional, porém com uma
Listagem 10. Exemplo de gluing functions. lógica tão complicada que passe a ser difícil de en-
Integer[] numbers = new Integer[]{3, 2, 4}; tender, difícil de testar ou impossível de separar em
Arrays.sort(numbers, new Comparator<Integer>() { módulos.
public int compare(Integer o1, Integer o2) { \."!201%0,- 8- 1040++E)&.- +!>0)- $'5!)- 3$!1/.-
return o1.compareTo(o2); aplicar programação funcional ou não. Também é ne-
} 40++E)&.- "0)&V4!)- +0- !6'&4!1/.- 6).5)!2!:;.- 9$14&.-
}); 1!'-02-+0$-4]/&5.-".4I-+0)E->010V4&!/.-60'!+-"!1%!-
System.out.println(Arrays.toString(numbers)); 501+-!6)0+01%!/!+-!3$&-<.$-.$%)!+=-.$-1;.#

/ 52
Functors e Apache Functor Listagem 12. Multiplicando um valor por dois com
(%8-!5.)!-$%&'&7!2.+-.-%0)2.-9$1:;.-/0-2!10&)!- uma Unary Function.
bem generalizada com o intuito de reduzir a com- public static UnaryFunction<Integer, Integer> doubler =
6'0A&/!/0-/.-!++$1%.#-(-6!)%&)-/!3$&-&)02.+-2.+%)!)- new UnaryFunction<Integer, Integer>() {
mais alguns termos usados em linguagens funcio- public Integer evaluate(Integer number) {
1!&+,->02-4.2.-1.-(6!4?0-j$14%.)-OdQ#- return number*2;
`- 6)&20&).- %0)2.- 8- 9$14%.)#- n2- 9$14%.)- 8- $2- }
termo usado quando modelamos objetos para que re- };
6)0+01%02-9$1:g0+,-4.2.-02-2!%02E%&4!-0-']5&4!#-`-
(6!4?0-j$14%.)-6.++$&-%)I+-9$14%.)+-6)&14&6!&+C-9$14- Essa função recebe apenas um argumento, logo
tions, predicates e procedures. 8- $2!- n1!)*- j$14%&.1#- `-(6!4?0- j$14%.)- +0- $%&'&7!-
`-(6!4?0-j$14%.)-%0"0-$2!-4?!2!/!-6!)!-".%.+- /0-S!"!-l010)&4+-<6!)!-"0)-2!&+-+.>)0-&++.,-4.1+$'%0-!-
6!)!-)0'0!+0-/!-+$!-"0)+;.-J#G-02-.$%$>).-/0+%0-!1.,- 0/&:;.-Wm-/!-c$1/.S=-6!)!-2./0'!)-9$14%.)+#-(++&2,-
porém o release foi adiado por haver itens a serem /0V1&2.+- .+- %&6.+- /.+- !)5$201%.+- 0- /.- )0%.)1.- /!-
20'?.)!/.+-1!-(N@#-(-j$1/!:;.-(6!4?0-6.++$&-$2!- função no momento em que a criamos.
série de diretrizes e valores que os projetos e suas co-
munidades seguem. Porém é esperado que ainda este Predicates
!1.-+!&!-!-"0)+;.-J#G-/.-(6!4?0-j$14%.)#- Em português, uma oração possui sujeito e pre-
(&1/!-!++&2,-6)090)&-$%&'&7!)-$2!-+1!6+?.%-/0++!- /&4!/.#-`-+$ 0&%.-8-+.>)0-3$02-9!'!2.+-1!-.)!:;.,-0-.-
(N@-!=-60'!-2!10&)!-4.2.-.+-+0$+-.> 0%.+-0+%;.-+01/.- predicado é tudo que falamos sobre ele. Na seguinte
modelados, b) por ser voltada somente para progra- .)!:;.-r.-1M20).-8-6!)s,-.-+$ 0&%.-8-1M20).-0-.-)0+-
2!:;.-9$14&.1!'-</&90)01%0-/.-l$!"!=-0-4=-6.)-4.1?0- %!1%0- 8- .- 6)0/&4!/.#- \0+%0- 4!+.,- .- 6)0/&4!/.- /0V10-
cer o nível de qualidade e maturidade que projetos 3$0-$2-1M20).-8-6!)#-N./02.+-%0+%E_'.-02-S!"!-/!-
(6!4?0-+;.-90&%.+# seguinte maneira.
Listagem 13. 4(,$&56%78"-("* "%9 (,8":";6,"76"
Functions maneira convencional, com um método.
j$14%&.1+- i- 9$1:g0+- i- +;.- 9$14%.)+- 3$0- 6./02-
)040>0)-!)5$201%.+-0-)0%.)1!2-$2-`> 0%.#-n2!-9$1- public boolean isEven(Integer number) {
:;.-6./0-+0)-4'!++&V4!/!-3$!1%.-!.-1M20).-/0-!)5$- return number % 2 == 0;
}
201%.+#- (++&2,- %02.+- 9$1:g0+- 1$''!)*- <.$- 1$'E)&!,-
101?$2-!)5$201%.=,-$1!)*-<.$-$1E)&!,-$2-M1&4.-!)-
Porém se escrevermos um novo programa, pro-
5$201%.=,->&1!)*-<>&1E)&!,-/.&+-!)5$201%.+=,-%0)1!)*-
vavelmente precisaremos escrever um código muito
<%0)1E)&!,-%)I+-!)5$201%.+=-0-!++&2-6.)-/&!1%0#
semelhante ao acima para testar o mesmo predicado.
o!2.+-+$6.)-3$0-/$)!1%0-.-/0+01".'"&201%.-/0-
(- 1;.- +0)- 3$0- 014!6+$'02.+- &++.- 02- !'5$2- %&6.- /0-
$2-+&+%02!,-60)40>02.+-3$0-0+4)0"02.+-"E)&!+-"070+-
abstração.
o mesmo trecho de código que calcula o dobro de um
Em programação funcional, podemos criar um
número.
predicate que testa se um número é par ou não. Como
Listagem 11. Multiplicando um valor por dois de E-"&2.+-!1%0)&.)201%0,-02-"07-/0-4)&!)2.+-$2-28-
maneira imperativa. %./.- .$- "!)&E"0',- 1.++.- 6)0/&4!%0- +0- %.)1!- $2- V)+%-
-class value, neste caso um objeto.
public int doubleValue(int number) { Listagem 14. 4(,$&56%78"-("* "%9 (,8":";6,"58 "
return number*2; um Unary Predicate.
}
public static UnaryPredicate<Integer> isEven =
new UnaryPredicate<Integer>() {
Podemos criar uma função que realize essa ope- public boolean test(Integer number) {
)!:;.#-R02>)0_+0,-28%./.+-1;.-+;.-V)+%_4'!++-"!'$0+,- return number %2 == 0;
E-9$1:g0+-+&2#-`$-+0 !,-6./02.+-$%&'&7!)-!+-9$1:g0+- }
};
02-/&"0)+.+-'.4!&+-/.-1.++.-4]/&5.#-SE-.-20+2.-1;.-
é verdadeiro com métodos, uma vez que precisamos
`-6)0/&4!/.-!4&2!-%!2>82-6./0-+0)-&1%0)6)0%!-
6!++!)- $2- .> 0%.- 6!)!- 3$0- 6.++!2.+- !40++E_'.#- (+-
do como uma função que retorna um valor boolean. E
sim, no nosso programa, em vez de duplicarmos o
como este predicado recebe apenas um argumento, é
código, temos a lógica encapsulada em apenas um
um Unary Predicate. Podemos utilizar esse predicado
lugar, bem testado e sendo utilizado de maneira mo-
02- $2- 2]/$'.- 4.2$2- !- "E)&.+- +&+%02!+- 1.+- 3$!&+-
/$'!)#-D-'02>)0_+0,-kUp-<k.1q%-U060!%-p.$)+0'9=-OJGQ#
ele seja utilizado, reduzindo o retrabalho.

53 \
Procedures Há casos em que preciso realmente de
Da mesma maneira que predicados, procedures programação funcional?
%!2>82-+;.-9$1:g0+#-N.)82-6).40/$)0+-+;.-9$1:g0+- Z.2040&-!-0+%$/!)-4.2-2!&+-!V14.-6).5)!2!-
3$0-1;.-)0%.)1!2-101?$2-"!'.)#-o!2.+-4.20:!)-9!- :;.-9$14&.1!'-?E-2!&+-.$-201.+-$2-!1.,-3$!1/.-
zendo um método que imprima um número. 4.2040&-!-2./0'!)-!-(N@-10>$'!)-i-10>$'!)#+9#10%#-
\0>$'!)-8-$2-0A026'.-&1%0)0++!1%0-6!)!-!6'&4!:;.-
Listagem 15. Imprimindo um número usando um
/0-6).5)!2!:;.-9$14&.1!'#-D'!-8-$2!-(N@-/0-']5&4!-
método.
9$77*-02-S!"!-0-$2-e@N-i-e.)h-@1-N).5)0++#-
public void printNumber(Integer number) { Lógica fuzzy em Java é tema para outro arti-
System.out.print(number + “ “); 5.,- 6.)82- ?E- $2!- 6!)%0- /0++!- ']5&4!- .1/0- 2.1-
} %!2.+-4.1 $1%.+-9$77*-0-9$1:g0+-/0-202>0)+?&6#-
(- 9$1:;.- /0- 202>0)+?&6- 8- 2$&%.- 6!)%&4$'!)- /0-
Podemos criar uma procedure que imprima um 4!/!- 6).5)!2!#- (6'&4!1/.- 6).5)!2!:;.- 9$14&.-
número passado para ela por argumento. Como esta 1!',- 6./02.+- /0&A!)- !- 9$1:;.- +0)- &26'0201%!/!-
6).40/$)0-)040>0)E-!601!+-$2-!)5$201%.,-+0)E-$2!- 60'.-$+$E)&.-<0'0-4)&!-40)%.-9$14%.)=-0-2./0'!2.+-
Unary Procedure. os objetos em Java para que tenhamos conjuntos
fuzzy.
Listagem 16. Imprimindo um número com Unary
Como você pode ver, dependendo de como
Predicate
".4I-2./0'!)-+$!-(N@,-".4I-6./0-$%&'&7!)-6).5)!-
public static UnaryProcedure<Integer> printNumber = mação funcional, às vezes sem nem perceber
new UnaryProcedure<Integer>() {
public void run(Integer number) { Comparando programação funcional
System.out.print(number + “ “);
}
com programação orientada a objetos
}; (++&2- 4.2.- !- 6).5)!2!:;.- 9$14&.1!'- 8- $2- 6!-
radigma em computação, programação orientada a
o.&'Yt-T05$&1/.-!-20+2!-!>.)/!502,-".4I-6./0- .> 0%.+-%!2>82-.-8#-N.)82-$%&'&7!)-$2!-1;.-+&51&V4!-
criar uma classe que imprima em um log especial tal- 0A4'$&)-!-.$%)!#-D2-6).5)!2!:;.-.)&01%!/!-!-.> 0%.+,-
vez. E seus testes garantirão que aquela funcionalida- aprendemos que usamos herança para reúso de mé-
de esteja de acordo com o contrato dela. todos e propriedades; e sobrescrita de métodos para
especialização.
Juntando os functors Listagem 18. Exemplo de herança e Orientação a
b$0- %!'- +0- $1%E++02.+- 1.++.+- 9$14%.)+- 02- $2- Objetos.
+]u- n2!- r9$14&.1!'&/!/0s- /.- 1.++.- +&+%02!- 3$0- public abstract class AbstractParser {
&26)&20- .- "!'.)- /.+- 1M20).+- 6!)0+- /$6'&4!/.#-o0 !-
!>!&A.-4.2.-V4!)&!-4.2-.-(6!4?0-j$14%.)# public abstract Message parse(String payload);

Listagem 17. Exemplo juntando os três functors public String !) *+& ,!""+-!,'.!/(0!() {
criados aqui, compondo uma nova função. // ...
return null;
public static void main(String[] args) { }
for( int i = 0 ; i <= 10 ; i++ ) {
if(IsEven.isEven.test(i)) { }
Integer doubledValue =
Doubler.doubler.evaluate(i); class SMSParser extends AbstractParser {
PrintNumber.printNumber.run(doubledValue); @Overridepubli
} public Message parse(String payload) {
} // ...
} }
}
Utilizamos todos os tipos que criamos para ela-
class MMSParser extends AbstractParser {
>.)!)- $2!- ).%&1!- 3$0- 0+%E- &26)&2&1/.- .- /.>).- /.- @Override
valor dos números pares encontrados em uma lista public Message parse(String payload) {
/0-&1%0&).+#-N./0)L!2.+-$%&'&7!)-0++!+-9$1:g0+-02-.$- // ...
%).+-6).5)!2!+,-2]/$'.+,->$1/'0+-`Tl&,-.$-3$!'3$0)- }
.$%)!-0+684&0-/0-2]/$'.#-D-4.2>&1E_'!+-6!)!-9.)2!)- }
1."!+-9$1:g0+#-
Em programação funcional, por outro lado, a

/ 54
!"#!$%&'!( )( #*+,+*-.+/( 0!( /123*( 4+( 5+*30&3( 67!"- "1%8!(%08+*+$$308+(#3*3(#*!2*3"34!*+$(+P#+*%+08+$<(
#!$%8%!0( 9.+*( :05+*%830 +;<( 7!"!( ,!%( .%$8!( 03( $+&'!( Normalmente, esses programadores, ao se depararem
anterior, em combinando diferentes functors, pode- com os princípios, vantagens, desvantagens e código-
"!$( !"=%03*( 4%,+*+08+$( ,10&>+$( #3*3( *%3*( 0!.3$( @+P+"#/!E(IQ( !"+&3"(3(#+0$3*(+"($%813&>+$(+"(M1+(
,10&>+$<( poderiam escrever código funcional.
R$8+(3*8%2!()(=+"(=Q$% !(+(.%$3("!$8*3*(4%.+*$3$(
Listagem 19. Exemplo de composição e programa- ,3 +83$(43(#*!2*3"3&'!(,10 %!03/<(O!*)"E(5Q("1%8!$(
ção funcional. outros tópicos que não foram cobertos aqui e que são
public class Parser { +P8*+"3"+08+(%"#!*8308+$E( !"!(3(3#/% 3&'!(4+(#*!-
gramação funcional em estrutura de dados. Também
private !"# UnaryFunction<String,Message>
seria possível nos aprofundarmos mais em cada um
parsingFunction;
dos princípios da programação funcional apresenta-
public Parser(UnaryFunction<String,Message> dos no início do artigo e discorrer com mais detalhes
parsingFunction) { a respeito de cada um.
this.parsingFunction = parsingFunction; H#+$3*( 4+( HO:$( +( /3"=43( +"( S3.3E( 3( /%02132+"(
} 3%043(4%? 1/83(1"(#!1 !(3(+$ *%83(4+( T4%2!(,10 %!-
nal. Se compararmos o código Java com um código
public Message parse(String payload) { que faça a mesma coisa em Ruby ou Scala, provavel-
return parsingFunction.evaluate(payload); "+08+( S3.3( 8+*Q( "3%$( /%053$( 4+( T4%2!( +( $+*Q( "3%$(
}
procedural.
} 9(#*!I+8!( !"(!$( T4%2!$@,!08+$(18%/%N34!$(0+$8+(
artigo estão disponíveis no site da revista.
class SMSParser implements UnaryFunction
<String, Message> {
public Message evaluate(String payload) { /referências
// ...
> !"# $%&'()*+ , -./)01+/(2 3*+4*(''1/4 -+* 56% 7%80 +&
return message;
Us. <http://www.defmacro.org/ramblings/fp.html>
}
} 9 !:# 56+';8+/< =1'+/ , 5>;% 56%+*> ? -./)01+/(2
3*+4*(''1/4@ A+';.01/4 B(C+*(0+*>< D/1E%*810> +& F(/0@
class MMSParser implements UnaryFunction G(*)6< "HHH@ I600;JKKLLL@)8@M%/0@()@.MK;%+;2%K80(&&K8N0K
<String, Message> { 55-3K9
public Message evaluate(String payload) { 9 !O# P*%4 G1)6(%28+/ , Q/ R/0*+$.)01+/ 0+ -./)01+/(2
// ... 3*+4*(''1/4 06*+.46 B('C$( A(2).2.8@ S%;(*0'%/0
return message; +& A+';.01/4 (/$ T2%0*1)(2 T/41/%%*1/4 , U%*1+0VW(00
} University, Edinburgh, Scotland. <http://www.macs.hw.ac.
} uk/~greg/books/>
9 !X# W(';2%*< S%(/ , -./)01+/(2 3*+4*(''1/4 &+* Y(E(
Pode-se também utilizar de lazy evaluation, S%E%2+;%*8@ Z[7%122> G%$1( R/)@< "\\] P*(E%/80%1/ U146L(>
,10 8%!0$( !"!(?*$8@ /3$$(.3/1+$(+(!18*!$(#*%0 -#%!$( ^+*06< =%C(80+;+2< AQ H]X_:@ :\""@
da programação funcional para termos reúso e espe- 9 !]# U(8M%22W1M1 , -./)01+/(2 3*+4*(''1/4@ I600;JKKLLL@
cialização. Poderíamos até combinar a função de par- haskell.org/haskellwiki/Functional_programming>
$%02(4+(AAB( !"(!18*3(4+(BA:C(64%$#!0-.+/(0!(AADE( 9 !`# G(006%L G1460 , 5*(/82(01/4 '(06 1/0+ )+$% L106
#*!8! !/!(#3*3(%08+*,3 +(+08*+(1"3(AAB7(F( +08*3/( %a(';2%8 1/ Y(E(< 7()M%0< U(8M%22 (/$ 3>06+/@ I600;JKK
AAB( F( +( 1"( #*!.+4!*( GHB( F( G3/1+( H44+4( B+*.% +;( '(00@'1460@/%0K(*01)2%8K$18)*%0%V'(06V(/$V)+$%K9
em uma só. Estaríamos aplicando gluing functions e 9 !_# b*1(/ P+%0c , =0(0% +& 06% B('C$(@ Z;%/YSF ,
higher-order functions. Mas isso não quer dizer que 3*+N%)0 B('C$( dY=7 OO]e@ I600;JKK)*@+;%/N$M@N(E(@
você não possa ter classes abstratas, ou que tenha /%0KfC*1(/4+%0cK2('C$(K2('C$(V80(0%VO@60'29@
que abandonar programação orientada a objetos. 9 !g# RbG S%E%2+;%*W+*M8 , G(80%*1/4 *%).*81E%
Uma importante qualidade para programadores programming. <http://www.ibm.com/developerworks/
)($3=+*(I1/23*(JKKL(M1304!(18%/%N3*(1"(!1(!18*!<(:$$!( 21/.aK21C*(*>K2V*%).*8K1/$%a@60'29
se aplica também a outros membros do time, como 9 !H# Q;()6% -./)0+*@ I600;JKK)+''+/8@(;()6%@+*4K
arquitetos e à escolha de arquiteturas, servidores de sandbox/functor/>
3#/% 3&'!E(HO:$( +( !18*!$( *+ 1*$!$( #3*3( 3( !0$8*1&'!( 9 !"\# 56% 3*(4'(01) b++M86%2& dQ/$*%L U./0 ? S(E1$
de um programa. 56+'(8e , 3*(4'(01) =+&0L(*% S%E%2+;'%/0 51;8@ I600;JKK
;*(4;*+4@)+'K06%V;*(4'(01)V;*+4*(''%*K%a0*()08K01;89
9 !""# Q(*+/ =L(*0c , U+L R 61*% ;*+4*(''%*8@ I600;JKK
$%!&'()*"+,)&- !"'& www.aaronsw.com/weblog/hiring>.
Programação funcional oferece um paradigma

55 \

Você também pode gostar