Functional Programming in Java - Lessons Learned by GridGain

4,817 views
4,705 views

Published on

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

0 Comments
6 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
4,817
On SlideShare
0
From Embeds
0
Number of Embeds
12
Actions
Shares
0
Downloads
116
Comments
0
Likes
6
Embeds 0
No embeds

No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • 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

    ×