Post on 10-May-2015
Refactoring to Macroswith Clojure
Dimitry Solovyov@dimituri
Let's talk aboutFUNCTIONAL PROGRAMMING
liftIO $ atomicModifyIORef sc $ \n -‐> (n + 1, ())
d <-‐ f v >>: onInner
liftIO $ ds `addDisposable` d
>>:
Let's talk about
LISP
LISP in 3 minutesvia @bodiltv
object.method(a, b);
object.method( a b)
Clojure
It's a LispCompiledDynamic typesType hintsMacros
Clojure
It's a LispCompiledDynamic typesType hintsMacrosOptional static typesOptional Prolog
HttpServer server = HttpServer.create(address, 0);server.createContext(path, handler);server.setExecutor(null);server.start();
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))
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.
(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))
根性
System.out.println(Encoding.encodeBase64(Encoding.decodeUrl(Encoding.decodeBase64(b))));
String url = Encoding.decodeBase64(b);String decodedUrl = Encoding.decodeUrl(url);String encodedUrl = Encoding.encodeBase64(decodedUrl);System.out.println(encodedUrl);
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)
-‐>
(-‐> 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 ,,,))
-‐<>-‐>>-‐>
(-‐> 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))
“Swiss Arrows”
-‐<>> -‐?<> -‐!> -‐!>>
-‐!<> <<-‐ -‐< -‐<:p
-‐<< -‐<<:p -‐<>< -‐<><:p
https://github.com/rplevy/swiss-arrows
-‐<<:p
-‐<<:p
Q: How do I get the result from a chain of computatoins that may fail?
PhoneNumber number = phoneMap.get(person);if (number != null) { Carrier carrier = carrierMap.get(number); if (carrier != null) { return addressMap.get(address); }}return null;
WHAT YOU'RE LOOKING FORIS AN OPTION MONAD
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))
Clojure vectors implement
java.lang.Comparablejava.util.RandomAccess
All Clojure functions implement
java.util.Comparatorjava.lang.Runnablejava.util.concurrent.Callable
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, 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));
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));
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));
(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"niluser=> (time (dotimes [i 1000000] (len-‐hinted (str i))))"Elapsed time: 113.317 msecs"nil
Polyglot projectswith 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
http://www.ldn.lv
Workshop: ClojureSaturday, May 18, 201310:00 am
Citadeles iela 12, Riga
http://riga.techhub.com/
(kthx-‐bye))))))
(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)))
(ns foo.core (:gen-‐class)) (defn -‐main "I don't do a whole lot ... yet." [& args] (println "I'm a little pony"))
foo$ lein runI'm a little pony
(defn make-‐example [] (proxy [Object] [] (toString [] "I'm a little pony")))
user=> (.toString (make-‐some-‐example))"I'm a little pony"
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))))
(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));