SlideShare a Scribd company logo
Finding Clojure




Kurt Harriger     @kurtharriger
The Challenge

Twitter search url filter
Project Folder
% lein new twitturl
Created 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”
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})
Appleholics
% brew install leiningen


       Non Appleholics
Find Leiningen for Clojure on
https://github.com/technomancy/leiningen
% lein self-install
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));
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));
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
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)])}))
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
Enter the repl
% lein deps
Copying 22 files to /Users/kurtharriger/code/twitturl/lib
Copying 17 files to /Users/kurtharriger/code/twitturl/lib/dev

% lein repl
REPL started; server listening on localhost:24319.
user=> (use ‘twitturl.core)
nil
user=> (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",
      ...
     }, ...]
   }
}
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
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")
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;
}
chaining
(defn format-tweet [tweet]   1         2
  [:li (:from_user tweet)
    [:blockquote (-> tweet :text linkify)]])

 Java:

 linkify(tweet.get(“text”))
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)?!
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;
}
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;
}
ring server
% lein ring server
2011-04-16 21:18:54.965:INFO::Logging to STDERR via org.mortbay.log.StdErrLog

2011-04-16 21:18:54.968:INFO::jetty-6.1.26

2011-04-16 21:18:54.998:INFO::Started SocketConnector@0.0.0.0:3000

Started server on port 3000



% lein ring war
Created /Users/kurtharriger/code/twitturl/twitturl-1.0.0-SNAPSHOT.war




Amazon Elastic Beanstalk plugin
https://github.com/weavejester/lein-beanstalk
Finding Clojure
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]))
10
11   (def   urls (partial re-seq #"http://S+"))
12
13   (defn linkify [text]
14     (reduce #(.replace %1 %2 (aslink %2)) text (urls text)))
15
16   (defn format-tweet [tweet]
17     [:li (:from_user tweet)
18      [:blockquote (-> tweet :text linkify)]])
19
20   (defn format-tweets [json]
21     [:ul (->> json :content :results
22               (remove #(-> % :text urls nil?))
23               (map format-tweet))])
24
25   (defn handler [{{q "q"} :params}]
26     { :content-type "text/html"
27      :body (html [:body (-> (search q) format-tweets)])})
28
29   (def app (-> handler wrap-params ))
Finding Clojure
    https://github.com/kurtharriger/twitturl
     Leiningen                Ring framework

     DSLs                     Lists are awesome

     Less () than Java        De-structuring

     Method chaining          High-order functions

Kurt Harriger            @kurtharriger

More Related Content

What's hot (20)

PDF
Jggug 2010 330 Grails 1.3 観察
Tsuyoshi Yamamoto
 
PDF
"PostgreSQL and Python" Lightning Talk @EuroPython2014
Henning Jacobs
 
PDF
The Ring programming language version 1.5.4 book - Part 40 of 185
Mahmoud Samir Fayed
 
PDF
The Ring programming language version 1.6 book - Part 15 of 189
Mahmoud Samir Fayed
 
PDF
Crawler 2
Cheng-Yi Yu
 
PPTX
QA Fest 2019. Saar Rachamim. Developing Tools, While Testing
QAFest
 
PDF
The Ring programming language version 1.10 book - Part 56 of 212
Mahmoud Samir Fayed
 
PDF
The Ring programming language version 1.7 book - Part 16 of 196
Mahmoud Samir Fayed
 
PDF
JJUG CCC 2011 Spring
Kiyotaka Oku
 
PPTX
Hadoop
Mukesh kumar
 
PDF
Python in the database
pybcn
 
PPT
GeeCON 2013 - EJB application guided by tests
Jakub Marchwicki
 
PPT
C# Application program UNIT III
Minu Rajasekaran
 
PDF
名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン
Tsuyoshi Yamamoto
 
PDF
The Ring programming language version 1.5.1 book - Part 24 of 180
Mahmoud Samir Fayed
 
KEY
Perl Web Client
Flavio Poletti
 
DOCX
VPN Access Runbook
Taha Shakeel
 
PDF
Finch.io - Purely Functional REST API with Finagle
Vladimir Kostyukov
 
DOCX
Fia fabila
fiafabila
 
PDF
201913001 khairunnisa progres_harian
KhairunnisaPekanbaru
 
Jggug 2010 330 Grails 1.3 観察
Tsuyoshi Yamamoto
 
"PostgreSQL and Python" Lightning Talk @EuroPython2014
Henning Jacobs
 
The Ring programming language version 1.5.4 book - Part 40 of 185
Mahmoud Samir Fayed
 
The Ring programming language version 1.6 book - Part 15 of 189
Mahmoud Samir Fayed
 
Crawler 2
Cheng-Yi Yu
 
QA Fest 2019. Saar Rachamim. Developing Tools, While Testing
QAFest
 
The Ring programming language version 1.10 book - Part 56 of 212
Mahmoud Samir Fayed
 
The Ring programming language version 1.7 book - Part 16 of 196
Mahmoud Samir Fayed
 
JJUG CCC 2011 Spring
Kiyotaka Oku
 
Hadoop
Mukesh kumar
 
Python in the database
pybcn
 
GeeCON 2013 - EJB application guided by tests
Jakub Marchwicki
 
C# Application program UNIT III
Minu Rajasekaran
 
名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン
Tsuyoshi Yamamoto
 
The Ring programming language version 1.5.1 book - Part 24 of 180
Mahmoud Samir Fayed
 
Perl Web Client
Flavio Poletti
 
VPN Access Runbook
Taha Shakeel
 
Finch.io - Purely Functional REST API with Finagle
Vladimir Kostyukov
 
Fia fabila
fiafabila
 
201913001 khairunnisa progres_harian
KhairunnisaPekanbaru
 

Viewers also liked (6)

PDF
Git Going With DVCS v1.5.2
Matthew McCullough
 
PDF
Job Hunting Under Duress
Matthew McCullough
 
PDF
Taming The JVM
Matthew McCullough
 
PDF
Git Going With DVCS v1.1
Matthew McCullough
 
PDF
Finding Things in Git
Matthew McCullough
 
PDF
JQuery Mobile
Matthew McCullough
 
Git Going With DVCS v1.5.2
Matthew McCullough
 
Job Hunting Under Duress
Matthew McCullough
 
Taming The JVM
Matthew McCullough
 
Git Going With DVCS v1.1
Matthew McCullough
 
Finding Things in Git
Matthew McCullough
 
JQuery Mobile
Matthew McCullough
 
Ad

Similar to Finding Clojure (20)

PDF
(first '(Clojure.))
niklal
 
PDF
Clojure class
Aysylu Greenberg
 
PDF
Clojure
Rohit Vaidya
 
ODP
Clojure made simple - Lightning talk
John Stevenson
 
PPTX
Web programming in clojure
bdemchak
 
PDF
Clojure presentation
Jéferson Machado
 
PDF
From Java To Clojure (English version)
Kent Ohashi
 
PDF
Clojure Programming Cookbook Makoto Hashimoto Nicolas Modrzyk
mbouemugnia
 
PDF
Exploring Clojurescript
Luke Donnet
 
PPTX
Clojure through the eyes of a Java Nut | [Mixed Nuts] at Pramati Technologies
Pramati Technologies
 
PDF
Scala4sling
day
 
PDF
Clojure Workshop: Web development
Sytac
 
PDF
Clojure 1.1 And Beyond
Mike Fogus
 
PDF
Writing a REST Interconnection Library in Swift
Pablo Villar
 
PDF
ClojureScript for the web
Michiel Borkent
 
KEY
(map Clojure everyday-tasks)
Jacek Laskowski
 
PDF
Clojure: Simple By Design
All Things Open
 
KEY
Unfiltered Unveiled
Wilfred Springer
 
PDF
ClojureScript - Making Front-End development Fun again - John Stevenson - Cod...
Codemotion
 
PDF
Brief intro to clojure
Roy Rutto
 
(first '(Clojure.))
niklal
 
Clojure class
Aysylu Greenberg
 
Clojure
Rohit Vaidya
 
Clojure made simple - Lightning talk
John Stevenson
 
Web programming in clojure
bdemchak
 
Clojure presentation
Jéferson Machado
 
From Java To Clojure (English version)
Kent Ohashi
 
Clojure Programming Cookbook Makoto Hashimoto Nicolas Modrzyk
mbouemugnia
 
Exploring Clojurescript
Luke Donnet
 
Clojure through the eyes of a Java Nut | [Mixed Nuts] at Pramati Technologies
Pramati Technologies
 
Scala4sling
day
 
Clojure Workshop: Web development
Sytac
 
Clojure 1.1 And Beyond
Mike Fogus
 
Writing a REST Interconnection Library in Swift
Pablo Villar
 
ClojureScript for the web
Michiel Borkent
 
(map Clojure everyday-tasks)
Jacek Laskowski
 
Clojure: Simple By Design
All Things Open
 
Unfiltered Unveiled
Wilfred Springer
 
ClojureScript - Making Front-End development Fun again - John Stevenson - Cod...
Codemotion
 
Brief intro to clojure
Roy Rutto
 
Ad

More from Matthew McCullough (20)

PDF
Using Git and GitHub Effectively at Emerge Interactive
Matthew McCullough
 
PDF
All About GitHub Pull Requests
Matthew McCullough
 
PDF
Adam Smith Builds an App
Matthew McCullough
 
PDF
Git's Filter Branch Command
Matthew McCullough
 
PDF
Git Graphs, Hashes, and Compression, Oh My
Matthew McCullough
 
PDF
Git and GitHub at the San Francisco JUG
Matthew McCullough
 
PDF
Git and GitHub for RallyOn
Matthew McCullough
 
PDF
Migrating from Subversion to Git and GitHub
Matthew McCullough
 
PDF
Git Notes and GitHub
Matthew McCullough
 
PDF
Intro to Git and GitHub
Matthew McCullough
 
PDF
Build Lifecycle Craftsmanship for the Transylvania JUG
Matthew McCullough
 
PDF
Git Going for the Transylvania JUG
Matthew McCullough
 
PDF
Transylvania JUG Pre-Meeting Announcements
Matthew McCullough
 
PDF
Game Theory for Software Developers at the Boulder JUG
Matthew McCullough
 
PDF
Cascading Through Hadoop for the Boulder JUG
Matthew McCullough
 
PDF
R Data Analysis Software
Matthew McCullough
 
PDF
Please, Stop Using Git
Matthew McCullough
 
PDF
Dr. Strangedev
Matthew McCullough
 
PDF
Jenkins for One
Matthew McCullough
 
PDF
Lean Fluffy Startups
Matthew McCullough
 
Using Git and GitHub Effectively at Emerge Interactive
Matthew McCullough
 
All About GitHub Pull Requests
Matthew McCullough
 
Adam Smith Builds an App
Matthew McCullough
 
Git's Filter Branch Command
Matthew McCullough
 
Git Graphs, Hashes, and Compression, Oh My
Matthew McCullough
 
Git and GitHub at the San Francisco JUG
Matthew McCullough
 
Git and GitHub for RallyOn
Matthew McCullough
 
Migrating from Subversion to Git and GitHub
Matthew McCullough
 
Git Notes and GitHub
Matthew McCullough
 
Intro to Git and GitHub
Matthew McCullough
 
Build Lifecycle Craftsmanship for the Transylvania JUG
Matthew McCullough
 
Git Going for the Transylvania JUG
Matthew McCullough
 
Transylvania JUG Pre-Meeting Announcements
Matthew McCullough
 
Game Theory for Software Developers at the Boulder JUG
Matthew McCullough
 
Cascading Through Hadoop for the Boulder JUG
Matthew McCullough
 
R Data Analysis Software
Matthew McCullough
 
Please, Stop Using Git
Matthew McCullough
 
Dr. Strangedev
Matthew McCullough
 
Jenkins for One
Matthew McCullough
 
Lean Fluffy Startups
Matthew McCullough
 

Recently uploaded (20)

PPTX
I INCLUDED THIS TOPIC IS INTELLIGENCE DEFINITION, MEANING, INDIVIDUAL DIFFERE...
parmarjuli1412
 
PDF
Stepwise procedure (Manually Submitted & Un Attended) Medical Devices Cases
MUHAMMAD SOHAIL
 
PPTX
THE HUMAN INTEGUMENTARY SYSTEM#MLT#BCRAPC.pptx
Subham Panja
 
PPTX
Unlock the Power of Cursor AI: MuleSoft Integrations
Veera Pallapu
 
PPTX
Orientation MOOCs on SWAYAM for Teachers
moocs1
 
PPTX
DIARRHOEA & DEHYDRATION: NURSING MANAGEMENT.pptx
PRADEEP ABOTHU
 
PPTX
Digital Professionalism and Interpersonal Competence
rutvikgediya1
 
PPTX
quizbeenutirtion-230726075512-0387d08e.pptx
domingoriahlyne
 
PDF
Tips for Writing the Research Title with Examples
Thelma Villaflores
 
PPTX
IDEAS AND EARLY STATES Social science pptx
NIRANJANASSURESH
 
PPTX
Gupta Art & Architecture Temple and Sculptures.pptx
Virag Sontakke
 
PPTX
Virus sequence retrieval from NCBI database
yamunaK13
 
PDF
TOP 10 AI TOOLS YOU MUST LEARN TO SURVIVE IN 2025 AND ABOVE
digilearnings.com
 
PPTX
YSPH VMOC Special Report - Measles Outbreak Southwest US 7-20-2025.pptx
Yale School of Public Health - The Virtual Medical Operations Center (VMOC)
 
PPTX
Electrophysiology_of_Heart. Electrophysiology studies in Cardiovascular syste...
Rajshri Ghogare
 
PDF
water conservation .pdf by Nandni Kumari XI C
Directorate of Education Delhi
 
PPTX
Various Psychological tests: challenges and contemporary trends in psychologi...
santoshmohalik1
 
PDF
Module 1: Determinants of Health [Tutorial Slides]
JonathanHallett4
 
PPTX
TOP 10 AI TOOLS YOU MUST LEARN TO SURVIVE IN 2025 AND ABOVE
digilearnings.com
 
PPTX
INTESTINALPARASITES OR WORM INFESTATIONS.pptx
PRADEEP ABOTHU
 
I INCLUDED THIS TOPIC IS INTELLIGENCE DEFINITION, MEANING, INDIVIDUAL DIFFERE...
parmarjuli1412
 
Stepwise procedure (Manually Submitted & Un Attended) Medical Devices Cases
MUHAMMAD SOHAIL
 
THE HUMAN INTEGUMENTARY SYSTEM#MLT#BCRAPC.pptx
Subham Panja
 
Unlock the Power of Cursor AI: MuleSoft Integrations
Veera Pallapu
 
Orientation MOOCs on SWAYAM for Teachers
moocs1
 
DIARRHOEA & DEHYDRATION: NURSING MANAGEMENT.pptx
PRADEEP ABOTHU
 
Digital Professionalism and Interpersonal Competence
rutvikgediya1
 
quizbeenutirtion-230726075512-0387d08e.pptx
domingoriahlyne
 
Tips for Writing the Research Title with Examples
Thelma Villaflores
 
IDEAS AND EARLY STATES Social science pptx
NIRANJANASSURESH
 
Gupta Art & Architecture Temple and Sculptures.pptx
Virag Sontakke
 
Virus sequence retrieval from NCBI database
yamunaK13
 
TOP 10 AI TOOLS YOU MUST LEARN TO SURVIVE IN 2025 AND ABOVE
digilearnings.com
 
YSPH VMOC Special Report - Measles Outbreak Southwest US 7-20-2025.pptx
Yale School of Public Health - The Virtual Medical Operations Center (VMOC)
 
Electrophysiology_of_Heart. Electrophysiology studies in Cardiovascular syste...
Rajshri Ghogare
 
water conservation .pdf by Nandni Kumari XI C
Directorate of Education Delhi
 
Various Psychological tests: challenges and contemporary trends in psychologi...
santoshmohalik1
 
Module 1: Determinants of Health [Tutorial Slides]
JonathanHallett4
 
TOP 10 AI TOOLS YOU MUST LEARN TO SURVIVE IN 2025 AND ABOVE
digilearnings.com
 
INTESTINALPARASITES OR WORM INFESTATIONS.pptx
PRADEEP ABOTHU
 

Finding Clojure

  • 3. Project Folder % lein new twitturl Created 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. 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. Appleholics % brew install leiningen Non Appleholics Find Leiningen for Clojure on https://github.com/technomancy/leiningen % lein self-install
  • 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. 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. 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. 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. 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. Enter the repl % lein deps Copying 22 files to /Users/kurtharriger/code/twitturl/lib Copying 17 files to /Users/kurtharriger/code/twitturl/lib/dev % lein repl REPL started; server listening on localhost:24319. user=> (use ‘twitturl.core) nil user=> (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. 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. 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. 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. chaining (defn format-tweet [tweet] 1 2 [:li (:from_user tweet) [:blockquote (-> tweet :text linkify)]]) Java: linkify(tweet.get(“text”))
  • 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. 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. 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. ring server % lein ring server 2011-04-16 21:18:54.965:INFO::Logging to STDERR via org.mortbay.log.StdErrLog 2011-04-16 21:18:54.968:INFO::jetty-6.1.26 2011-04-16 21:18:54.998:INFO::Started [email protected]:3000 Started server on port 3000 % lein ring war Created /Users/kurtharriger/code/twitturl/twitturl-1.0.0-SNAPSHOT.war Amazon Elastic Beanstalk plugin https://github.com/weavejester/lein-beanstalk
  • 21. 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])) 10 11 (def urls (partial re-seq #"http://S+")) 12 13 (defn linkify [text] 14 (reduce #(.replace %1 %2 (aslink %2)) text (urls text))) 15 16 (defn format-tweet [tweet] 17 [:li (:from_user tweet) 18 [:blockquote (-> tweet :text linkify)]]) 19 20 (defn format-tweets [json] 21 [:ul (->> json :content :results 22 (remove #(-> % :text urls nil?)) 23 (map format-tweet))]) 24 25 (defn handler [{{q "q"} :params}] 26 { :content-type "text/html" 27 :body (html [:body (-> (search q) format-tweets)])}) 28 29 (def app (-> handler wrap-params ))
  • 22. Finding Clojure https://github.com/kurtharriger/twitturl Leiningen Ring framework DSLs Lists are awesome Less () than Java De-structuring Method chaining High-order functions Kurt Harriger @kurtharriger