More Related Content Similar to Refactoring to Macros with Clojure Similar to Refactoring to Macros with Clojure (20) More from Dmitry Buzdin (20) Refactoring to Macros with Clojure17. HttpServer
server
=
HttpServer.create(address,
0);
server.createContext(path,
handler);
server.setExecutor(null);
server.start();
18. HttpServer
server
=
HttpServer.create(address,
0);
server.createContext(path,
handler);
server.setExecutor(null);
server.start();
(doto
(HttpServer/create
address
0)
(.createContext
path
handler)
(.setExecutor
nil)
(.start))
19. macro |ˈmakrəәʊ|
noun ( pl. macros )
1 (also macro instruction) Computing a single instruction
that expands automatically into a set of instructions
to perform a particular task.
20. (let*
[G__360
(HttpServer/create
address
0)]
(.createContext
G__360
path
handler)
(.setExecutor
G__360
nil)
(.start
G__360)
G__360)
(doto
(HttpServer/create
address
0)
(.createContext
path
handler)
(.setExecutor
nil)
(.start))
23. String
url
=
Encoding.decodeBase64(b);
String
decodedUrl
=
Encoding.decodeUrl(url);
String
encodedUrl
=
Encoding.encodeBase64(decodedUrl);
System.out.println(encodedUrl);
24. String
url
=
Encoding.decodeBase64(b);
String
decodedUrl
=
Encoding.decodeUrl(url);
String
encodedUrl
=
Encoding.encodeBase64(decodedUrl);
System.out.println(encodedUrl);
(-‐>
b
Encoding/decodeBase64
Encoding/decodeUrl
Encoding/encodeBase64
println)
26. -‐>>-‐>
(-‐>
stuff
(foo
,,,
a)
(bar
,,,
b
c
d)
(baz
,,,
e
f))
(-‐>>
stuff
(foo
a
,,,)
(bar
b
c
d
,,,)
(baz
e
f
,,,))
27. -‐<>-‐>>-‐>
(-‐>
stuff
(foo
,,,
a)
(bar
,,,
b
c
d)
(baz
,,,
e
f))
(-‐>>
stuff
(foo
a
,,,)
(bar
b
c
d
,,,)
(baz
e
f
,,,))
(-‐<>
stuff
(foo
a
<>)
(bar
b
c
<>
d)
(baz
<>
e
f))
31. Q: How do I get the result from a
chain of computatoins that may fail?
32. PhoneNumber
number
=
phoneMap.get(person);
if
(number
!=
null)
{
Carrier
carrier
=
carrierMap.get(number);
if
(carrier
!=
null)
{
return
addressMap.get(address);
}
}
return
null;
35. PhoneNumber
number
=
phoneMap.get(person);
if
(number
!=
null)
{
Carrier
carrier
=
carrierMap.get(number);
if
(carrier
!=
null)
{
return
addressMap.get(address);
}
}
return
null;
(some-‐>>
(.get
phoneMap
person)
(.get
carrierMap)
(.get
addressMap))
37. All Clojure functions implement
java.util.Comparator
java.lang.Runnable
java.util.concurrent.Callable
38. List<Integer>
numbers
=
Arrays.asList(1,
3,
4,
8,
2);
Collections.sort(numbers,
new
Comparator<Integer>()
{
@Override
public
int
compare(Integer
o1,
Integer
o2)
{
return
o2.compareTo(o1);
}
});
39. List<Integer>
numbers
=
Arrays.asList(1,
3,
4,
8,
2);
Collections.sort(numbers,
new
Comparator<Integer>()
{
@Override
public
int
compare(Integer
o1,
Integer
o2)
{
return
o2.compareTo(o1);
}
});
List<Integer>
numbers
=
Arrays.asList(1,
3,
4,
8,
2);
Collections.sort(numbers,
(o1,
o2)
-‐>
o2.compareTo(o1));
40. List<Integer>
numbers
=
Arrays.asList(1,
3,
4,
8,
2);
Collections.sort(numbers,
new
Comparator<Integer>()
{
@Override
public
int
compare(Integer
o1,
Integer
o2)
{
return
o2.compareTo(o1);
}
});
(doto
(ArrayList.
[1
3
4
8
2])
(Collections/sort
(fn
[o1
o2]
(.compareTo
o2
o1))))
List<Integer>
numbers
=
Arrays.asList(1,
3,
4,
8,
2);
Collections.sort(numbers,
(o1,
o2)
-‐>
o2.compareTo(o1));
41. List<Integer>
numbers
=
Arrays.asList(1,
3,
4,
8,
2);
Collections.sort(numbers,
new
Comparator<Integer>()
{
@Override
public
int
compare(Integer
o1,
Integer
o2)
{
return
o2.compareTo(o1);
}
});
(doto
(ArrayList.
[1
3
4
8
2])
(Collections/sort
(fn
[o1
o2]
(.compareTo
o2
o1))))
(sort
#(compare
%2
%1)
[1
3
4
8
2])
List<Integer>
numbers
=
Arrays.asList(1,
3,
4,
8,
2);
Collections.sort(numbers,
(o1,
o2)
-‐>
o2.compareTo(o1));
43. (defn
len-‐reflected
[s]
(.length
s))
(defn
len-‐hinted
^String
[^String
s]
(.length
s))
user=>
(time
(dotimes
[i
1000000]
(len-‐reflected
(str
i))))
"Elapsed
time:
3204.913
msecs"
nil
user=>
(time
(dotimes
[i
1000000]
(len-‐hinted
(str
i))))
"Elapsed
time:
113.317
msecs"
nil
44. Polyglot projects
with Leiningen
(defproject
clojure-‐java
"1.0.0-‐SNAPSHOT"
:description
"Example
Clojure+Java
project."
:min-‐lein-‐version
"2.0.0"
:source-‐paths
["src/clojure"]
:java-‐source-‐paths
["src/java"]
:javac-‐options
["-‐target"
"1.5"
"-‐source"
"1.5"])
http://leiningen.org
47. (defmacro
doto
[x
&
forms]
(let
[gx
(gensym)]
`(let
[~gx
~x]
~@(map
(fn
[f]
(if
(seq?
f)
`(~(first
f)
~gx
~@(next
f))
`(~f
~gx)))
forms)
~gx)))
48. (ns
foo.core
(:gen-‐class))
(defn
-‐main
"I
don't
do
a
whole
lot
...
yet."
[&
args]
(println
"I'm
a
little
pony"))
foo$
lein
run
I'm
a
little
pony
49. (defn
make-‐example
[]
(proxy
[Object]
[]
(toString
[]
"I'm
a
little
pony")))
user=>
(.toString
(make-‐some-‐example))
"I'm
a
little
pony"
50. class
Example
{
void
someMethod(String
x)
{
someMethod(x,
null)
}
void
someMethod(String
x,
String
y)
{
doSomethingWith(x,
y);
}
}
(proxy
[Example]
[]
(toString
([x]
(proxy-‐super
someMethod
x))
([x
y]
(do-‐other-‐stuff
this
x
y))))
51. (let
[^LoadingCache
cache
(doto
CacheBuilder/newBuilder
(.maximumSize
1000)
(.build
(reify
CacheLoader
(load
^Graph
[^Key
key]
(create-‐expensive-‐graph
key)))))])
LoadingCache<Key,
Graph>
cache
=
CacheBuilder.newBuilder()
.maximumSize(1000)
.build(new
CacheLoader<Key,
Graph>()
{
public
Graph
load(Key
key)
{
return
createExpensiveGraph(key);
}
});
LoadingCache<Key,
Graph>
cache
=
CacheBuilder.newBuilder()
.maximumSize(1000)
.build((key)
-‐>
createExpensiveGraph(key));