Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Functional Programming in Java - Lessons Learned by GridGain

5,041 views

Published on

10 lessons learned by GridGain in developing GridGain 3.0 that incorporates Java-based distributed Functional Programming (FP) framework.

Functional Programming in Java - Lessons Learned by GridGain

  1. 1. Func%onal
Programming
in
Java Lessons
Learned
by
GridGain








@gridgain JavaOne
2010 www.gridgain.com
  2. 2. Take
Away
Point> “FP
Works
In
Java
If
You
Do
It
Right” > It
work
even
in
Java
6 > It
carries
many
of
the
FP
benefits
from
pure
FP
languages > Java
7
will
make
it
a
bit
more
elegant> Agenda > FP
quick
introduc7on > Top
10
lessons
learned > Q&A Func7onal
Programming
in
Java:
Lessons
Learned
by
GridGain Slide
 2
  3. 3. FP
Quick
Introduc%on> General > First‐class
&
higher‐order
func7ons > Pure
func7ons
‐
no
side
effects
and
referen7al
opaqueness > Currying
as
par7al
func7on
applica7on > Recursion> Language
specific > Monads
and
collec7on
comprehension > PaSern
matching > Lazy
ini7aliza7on Func7onal
Programming
in
Java:
Lessons
Learned
by
GridGain Slide
 3
  4. 4. FP
Quick
Introduc%on
cont.> Java
+
FP
=
Post
Func7onal
system > Java
is
impera7ve
OOP
system > Java
+
FP
‐
Garbage
=
Scala> Pure
FP
languages
suck
in
object
domain
design
 > OO
is
way
beSer
in
describing
our
world> FP
excels
at
actual
coding
of
the
algorithm> Post
Func%onal
“manifesto”: > Use
OO
to
build
your
classes > Use
FP
to
implement
their
methods Func7onal
Programming
in
Java:
Lessons
Learned
by
GridGain Slide
 4
  5. 5. Lesson
1
‐
FP
Is
More
Than
Just
Cool
Concept...Impera7ve
GridGain
2.0 Functional


GridGain
3.0@Gridify(taskClass
=
Task.class) public
int
length(String
msg)
{public
int
length(String
msg)
{ 



return
G.grid().reduce(SPREAD,
F.yield(msg.split(“s”,
0),




return
msg.replaceAll("s",
"").length(); 







F.<String,
Integer>c1("length")),
F.sumIntReducer());} }class
Task
extends
GridifyTaskSplitAdapter<Integer>
{



@Override




protected
Collection<?
extends
GridJob>
split(int
gridSize,








GridifyArgument
arg)
throws
GridException
{







String
msg
=
(String)arg.getMethodParameters()[0];







String[]
words
=

msg.split("w",
0);













Collection<GridJob>
jobs
=
new
ArrayList<GridJob>();







for
(final
String
word
:
words)
{











jobs.add(new
GridJobAdapter()
{















@Override
















public
Object
execute()
throws
GridException
{



















return
word.length();















}











});







}







return
jobs;



}



@Override




public
Integer
reduce(List<GridJobResult>
results)
throws
GridException
{







int
length
=
0;







for
(GridJobResult
res
:
results)
{











length
+=
(Integer)res.getData();







}













return
length;




}} Func7onal
Programming
in
Java:
Lessons
Learned
by
GridGain Slide
 5
  6. 6. Lesson
2
‐
Typedes
Help
Reduce
Java
Bloat > Java,
unlike
Scala,
does
not
have
type
aliases > The
only
choice:
Inheritance > public
abstract
class
C1<E1,
R>
extends
GridClosure<E1,
R>
{} > public
class
F
extends
GridFunc
{} > Can
only
be
used
during
crea7on
for
stateful
classes > Can
be
used
as
a
real
alias
for
u7lity
classes > Without
typedef: return
GridFunc.isEmpty(a)
?
GridFunc.<T>alwaysFalse()
:
new
GridPredicate<T>()
{
...
} > With
typedefs: return
F.isEmpty(a)
?
F.<T>alwaysFalse()
:
new
P1<T>()
{
...
} Func7onal
Programming
in
Java:
Lessons
Learned
by
GridGain Slide
 6
  7. 7. Lesson
3
‐
Immutability
Actually
Works > CPU
and
memory
inefficiency
is
greatly
exaggerated
 > Copy‐On‐Write
structures
gebng
more
and
more
aSen7on > Strong
support
for
immutability
from
FP
library GridPredicate2<Integer,
Integer>
p
=
new
P2<Integer,
Integer>()
{ 



@Override
public
boolean
apply(Integer
i1,
Integer
i2)
{
return
i1
>
i2;
} }; Collection<Integer>
c
=
new
ArrayList<Integer>(); ... F.forEach(F.retain(c,
true,
p.curry(10)),
F.<Integer>print("",
"
"));
//
<
10. F.forEach(F.lose(c,
true,
p.curry(10)),
F.<Integer>print("",
"
"));
//
>=
10. Func7onal
Programming
in
Java:
Lessons
Learned
by
GridGain Slide
 7
  8. 8. Lesson
4
‐
Tuples
Reduce
Noise
POJOs > An
Obvious
Design
Pa8ern
forgoSen
in
99%
of
projects > Ideal
for: > Returning
mul7ple
value
from
the
methods
or
closure > Ac7ng
as
a
free
variable
in
the
closure for
(Object
obj
:
F.t(2,
0.5,
"tuple"))
{ 



System.out.println("Tuple
element:
"
+
obj); } ...
 GridTuple3<String,
Integer,
Boolean>
t
=
F.t("gridgain",
1,
false); String
s
=
t.get1(); int
i
=
t.get2(); boolean
b
=
t.get3(); Func7onal
Programming
in
Java:
Lessons
Learned
by
GridGain Slide
 8
  9. 9. Lesson
5
‐
Collec%ons
Comprehension
Without
Monads> Java
does
not
have
monad
support,
however...> ...similar
collec7on
comprehension
can
be
provided
via
API Collection<Integer>
nums
=
new
ArrayList<Integer>(); F.forEach(nums,
F.<Integer>print("",
"
")); int
max
=
F.fold(nums,
F.first(nums),
new
C2<Integer,
Integer,
Integer>()
{ 



@Override
public
Integer
apply(Integer
n,
Integer
max)
{
return
Math.max(n,
max);
} }); int
min
=
F.fold(nums,
F.first(nums),
new
C2<Integer,
Integer,
Integer>()
{ 



@Override
public
Integer
apply(Integer
n,
Integer
min)
{
return
Math.min(n,
min);
} }); int
sum
=
F.fold(nums,
0,
new
C2<Integer,
Integer,
Integer>()
{ 



@Override
public
Integer
apply(Integer
n,
Integer
sum)
{
return
sum
+
n;
} }); ... public
static
void
sayIt(String
phrase)
throws
GridException
{ 



G.grid().run(SPREAD,
F.yield(phrase.split("
"),
F.<String>printf("%sn"))); } Func7onal
Programming
in
Java:
Lessons
Learned
by
GridGain Slide
 9
  10. 10. Lesson
6
‐
Checked
Excep%ons
Do
Not
Work
(Unfortunately) > Closures
and
predicates
are
abstract
classes: public
abstract
class
GridClosure<E,
R>
{ 



public
abstract
R
apply(E
e);
//
Awkward
to
throw
an
exception... 



public
GridOutClosure<R>
curry(final
E
e)
{ 







return
new
CO<R>()
{ 











@Override
public
R
apply()
{
return
GridClosure.this.apply(e);
} 







}; 



} } ... GridClosure<Integer,
Integer>
sqr
=
new
C1<Integer,
Integer>()
{ 



@Override
public
Integer
apply(Integer
i)
{
return
i
*
i;
} }; Collection<Integer>
c
=
F.asList(1,
2,
3,
4);
 F.transform(c,
sqr);
//
1,
4,
9,
16 Func7onal
Programming
in
Java:
Lessons
Learned
by
GridGain Slide
 10
  11. 11. Lesson
7
‐
Accept
null
As
Alterna%ve
to
Op%on/Maybe > Op7ons/Maybe
is
extremely
powerful
concept
in
languages
like
Scala
or
Haskel > In
Java
‐
direct
implementa7on
is
largely
impossible
☹ > Closest
thing
‐
accept
null
collec7on
and
empty
varargs Scala Java
GridGain
3.0 val
value
=
for
{ public
static
<T>
boolean
isAll(@Nullable
T
t,
 row
<‐
database
fetchRowById
42 @Nullable
Iterable<?
extends
GridPredicate<T>>
p)
{ key
<‐
row
get
"port_key" 



if
(!isEmpty(p))
{ val
<‐
myMap
get
key 







assert
p
!=
null; }
yield
val 







for
(GridPredicate<T>
r
:
p)
{ val
result
=
value
getOrElse
defaultValue 











if
(r
!=
null
&&
!r.apply(t))
{ 















return
false; 











} 







} 



} 



return
true; } Func7onal
Programming
in
Java:
Lessons
Learned
by
GridGain Slide
 11
  12. 12. Lesson
8
‐
Last
Argument
as
vararg
of
Predicates > Very
useful
idiom
to
make
ordinary
methods
powerful: > You
can
pass
zero
predicates
(omit
parameter) > You
can
pass
just
one
predicate > You
can
pass
null
as
parameter > You
can
pass
array
as
parameter > You
can
pass
mul%ple
predicates...
all
in
one
signature
(!) > Used
globally
in
GridGain
project > One
of
the
most
radical
improvements
on
API //
Data
grid. forEach(GridInClosure<GridCacheEntry<K,
V>>
vis,
@Nullable
K...
keys); forAll(GridPredicate<GridCacheEntry<K,
V>>
vis,
@Nullable
K...
keys); reduce(GridReducer<GridCacheEntry<K,
V>,
R>
rdc,
@Nullable
K...
keys); loadCache(GridPredicate2<K,
V>
p,
long
ttl,
@Nullable
Object...
args); //
Closures
and
tasks
on
cloud. call(GridClosureCallMode
mode,
Callable<R>
job,
@Nullable
GridPredicate<GridRichNode>...
p); execute(String
taskName,
@Nullable
T
arg,
@Nullable
GridPredicate<GridRichNode>...
p); forkjoin(Collection<T>
jobs,
GridReducer<R1,
R2>
rdc,
@Nullable
GridPredicate<GridRichNode>...
p); run(GridClosureCallMode
mode,
Runnable
job,
@Nullable
GridPredicate<GridRichNode>...
p); send(Object
msg,
@Nullable
GridPredicate<GridRichNode>...
p) Func7onal
Programming
in
Java:
Lessons
Learned
by
GridGain Slide
 12
  13. 13. Lesson
9
‐
Func%on
Factory
vs.
new > Reduces
Java
Generics
bloat
by
type
inference > Widely
used
despite
“broken”
Generics
and
type
inference Compare: Iterator<Object>
iter
=
new
GridTuple3<String,
Integer,
Boolean>("a",
1,
false); vs.
 Iterator<Object>
iter
=
F.t("a",
1,
false); Func7onal
Programming
in
Java:
Lessons
Learned
by
GridGain Slide
 13
  14. 14. Lesson
10
‐
Learn
Scala
First! That
is
what
we
did
at
GridGain... ...and
that
is
the
only
reason
we
got
it
right
on
Java
side. Func7onal
Programming
in
Java:
Lessons
Learned
by
GridGain Slide
 14
  15. 15. Q
&
A Thank
You
For
Your
Time!Nikita
Ivanov:
nivanov@gridgain.com GridGain:
www.gridgain.com 








@gridgain Func7onal
Programming
in
Java:
Lessons
Learned
by
GridGain Slide
 15

×