Finding Clojure

2,124 views

Published on

Kurt Harriger's Ignite presentation to DOSUG on how to use Clojure to talk to web services.

Published in: Education
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,124
On SlideShare
0
From Embeds
0
Number of Embeds
17
Actions
Shares
0
Downloads
0
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Finding Clojure

  1. 1. Finding ClojureKurt Harriger @kurtharriger
  2. 2. The ChallengeTwitter search url filter
  3. 3. Project Folder% lein new twitturlCreated new project in: /Users/kurtharriger/code/twitturl├── README├── project.clj├── src│   └── twitturl│   └── core.clj└── test └── twitturl └── test └── core.clj % git init && git add -A && git commit -m “create project”
  4. 4. project.clj(defproject twitturl "1.0.0-SNAPSHOT" :description "Twitturl aggregator" :dependencies [[org.clojure/clojure "1.2.0"] [org.clojure/clojure-contrib "1.2.0"] [ring "0.3.7"] [clj-http "0.1.2"]] :dev-dependencies [[lein-ring "0.4.0"]] :ring {:handler twitturl.core/app})
  5. 5. Appleholics% brew install leiningen Non AppleholicsFind Leiningen for Clojure onhttps://github.com/technomancy/leiningen% lein self-install
  6. 6. S-Expressions Clojure: (defn fn [arg1 & more] arg1)defn is a macro used here with 3 parameters:function name, arguments, and body.Returns the function binding. Clojure: (println (fn value1 value2)) Java: System.out.println(fn(value1, value2));
  7. 7. S-Expressions Clojure: (defn fn [arg1 & more] arg1)defn is a macro used here with 3 parameters:function name, arguments, and body.Returns the function binding. Clojure: (println (fn value1 value2)) Java: System.out.println(fn(value1, value2));
  8. 8. ring framework(ns twitturl.core (:require [com.twinql.clojure.http :as http]) (:use [ring.middleware.params]) (:use [hiccup.core])) Import dependencies(defn handler [] nil) ;todo create handler(def app (-> handler wrap-params)) -> operator used apply multiple Entry point functions to handler
  9. 9. De-structuring(defn format-tweets [json] nil) ; todo(defn handler [{{q "q"} :params}] { :content-type "text/html" :body (html [:body (-> (search q) format-tweets)])})same as: Only need q(defn handler [request] (let [params (request :params) Local variable assignments q (params "q")] request and params {:content-type "text/html" unnecessary. :body (html [:body (-> (search q) format-tweets)])}))
  10. 10. The Search(def url "http://search.twitter.com/search.json") define readonly variable named url(defn search [query] (http/get url :query {:q query} :as :json)) returns result of com.twinql.clojure.http.get using parameter list 1) url 2) :query 3) {:q query } 4) :as 5) :json
  11. 11. Enter the repl% lein depsCopying 22 files to /Users/kurtharriger/code/twitturl/libCopying 17 files to /Users/kurtharriger/code/twitturl/lib/dev% lein replREPL started; server listening on localhost:24319.user=> (use ‘twitturl.core)niluser=> (search “clojure”){:code 200, :reason "OK", :content {:results [{:from_user "planetclojure", :text "Removing defined tests in Clojure REPL http://goo.gl/fb/qeUty #clojure #SO", ... }, ...] }}
  12. 12. The Handler(defn format-tweets [json] nil) ; todo(defn handler [{{q "q"} :params}] { :content-type "text/html" :body hiccup library function (html [:body (-> (search q) format-tweets)])}) same as (format-tweets (search q)) returns a map containing :content-type and :body
  13. 13. functions(defn aslink [url] (html [:a {:href url} url]))user=> (aslink “http://url1”)"<a href="http://url1">http://url1</a>"(def urls (partial re-seq #"http://S+"))same as:(defn urls [text] (re-seq #“http://S+” text))user=> (urls “blah blah http://url1 http://url2”)("http://url1" "http://url2")
  14. 14. map reduce(defn linkify [text] (reduce #(.replace %1 %2 (aslink %2)) text (urls text))) (fn [newText url] (.replace newText url (aslink url))String linkify(String text) { String newText = text; for(String url : getUrls(text)) { newText = newText.replace(url, asLink(url)); } return newText;}
  15. 15. chaining(defn format-tweet [tweet] 1 2 [:li (:from_user tweet) [:blockquote (-> tweet :text linkify)]]) Java: linkify(tweet.get(“text”))
  16. 16. chaining(defn format-tweet [tweet] 1 2 2 [:li (:from_user tweet) [:blockquote (-> tweet :text linkify)]]) Java: linkify(tweet.get(“text”)) 4 Java requires more(parentheses)?!
  17. 17. chaining(defn format-tweets [json] [:ul (->> json :content :results (remove #(-> % :text urls nil?)) (map format-tweet))])ArrayList<String> formatTweets(JSONObject json) { StringBuilder tweets = new StringBuilder(); tweets.append(“<ul>”); JSONObject content = json.getJSONObject(“content”); JSONArray results = json.getJSONArray(“results”); for(JSONObject tweet : results) { String[] urls = getUrls(tweet.getString(“text”)) if(urls != null && urls.length > 0) { tweets.append(“<li>” + formatTweet(tweet) “</li>”); } } tweets.append(“</ul>”); return tweets;}
  18. 18. chaining(defn format-tweets [json] 5 [:ul (->> json :content :results (remove #(-> % :text urls nil?)) (map format-tweet))])ArrayList<String> formatTweets(JSONObject json) { StringBuilder tweets = new StringBuilder(); tweets.append(“<ul>”); JSONObject content = json.getJSONObject(“content”); JSONArray results = json.getJSONArray(“results”); for(JSONObject tweet : results) { 12 String[] urls = getUrls(tweet.getString(“text”)) if(urls != null && urls.length > 0) { tweets.append(“<li>” + formatTweet(tweet) “</li>”); } } Java usually requires more(parentheses)?! tweets.append(“</ul>”); return tweets;}
  19. 19. ring server% lein ring server2011-04-16 21:18:54.965:INFO::Logging to STDERR via org.mortbay.log.StdErrLog2011-04-16 21:18:54.968:INFO::jetty-6.1.262011-04-16 21:18:54.998:INFO::Started SocketConnector@0.0.0.0:3000Started server on port 3000% lein ring warCreated /Users/kurtharriger/code/twitturl/twitturl-1.0.0-SNAPSHOT.warAmazon Elastic Beanstalk pluginhttps://github.com/weavejester/lein-beanstalk
  20. 20. src/twitturl/core.clj 1 (ns twitturl.core 2 (:use [ring.middleware.params]) 3 (:use [hiccup.core]) 4 (:require [com.twinql.clojure.http :as http])) 5 6 (def url "http://search.twitter.com/search.json") 7 8 (defn search [query] (http/get url :query {:q query} :as :json)) 9 (defn aslink [url] (html [:a {:href url} url]))1011 (def urls (partial re-seq #"http://S+"))1213 (defn linkify [text]14 (reduce #(.replace %1 %2 (aslink %2)) text (urls text)))1516 (defn format-tweet [tweet]17 [:li (:from_user tweet)18 [:blockquote (-> tweet :text linkify)]])1920 (defn format-tweets [json]21 [:ul (->> json :content :results22 (remove #(-> % :text urls nil?))23 (map format-tweet))])2425 (defn handler [{{q "q"} :params}]26 { :content-type "text/html"27 :body (html [:body (-> (search q) format-tweets)])})2829 (def app (-> handler wrap-params ))
  21. 21. Finding Clojure https://github.com/kurtharriger/twitturl Leiningen Ring framework DSLs Lists are awesome Less () than Java De-structuring Method chaining High-order functionsKurt Harriger @kurtharriger

×