Paul McCarthy’s Myth of the Artistic Greatness [The Other Politics in art] by Rosina Ivanova
(defn -main [& args] (talk/start clt-cljs)ben.vandgrift.com/talks/cltjs-101.pdfwhat is Lisp? John...
Transcript of (defn -main [& args] (talk/start clt-cljs)ben.vandgrift.com/talks/cltjs-101.pdfwhat is Lisp? John...
(defn -main [& args] (talk/start clt-cljs)
a møøse once bit my sister
Ben [email protected] / ben.vandgrift.com
(.log js/console “hello”)
consulting, open source, and Datomiccognitect.com & github.com/cognitect/clojurescript
the
marketing
slide!
Clojure Applied: From Practice to PractitionerPragmatic Programmers, beta available March 2015
the other
marketing
slide!
A rubyist, a clojurist, and a javascript programmer walks into a bar and has a beer.
—ben
ClojureScript 101?
or: “How I learned to stop worrying and love the parentheses.”
why?
what is ClojureScript?
an implementation of the Clojure with JS as its platform
what is Clojure*?
an advanced Lisp dialect designed for a concurrent world
on the JVM, right? yes and.
what is Lisp?
John McCarthy’s language for specifying mathematical notation (1958), based on the work of Alonzo Church’s lambda calculus (1930’s).
1958, seriously?
yes.
Clojure was built on well-researched principles over a
period of two years.
Rich Hickey’s ‘Clojure Bookshelf’
http://www.amazon.com/Clojure-Bookshelf/lm/R3LG3ZBZS4GCTH
• reasonability: the lambda calculus, Lisp
• metaprogramming (defmacro, etc)
• persistent data structures (vector, hash-map, etc)
• lazy and delayed evaluation (sequences)
• asynchronous evaluation (futures, promises)
• concurrent channels (core.async)
• state management (mvcc, uniform update model)
ClojureScript is Clojure
is Lisp
mostly…
.clj/s features
• homoiconicity
• immutability
• concurrency
• metadata
• functionalish
• composability
• interoperability
• macros
• bindings
• impressive!
the basics
Note the function position: (def a-var “some value”)
Note the quote: ‘(1 :two “3” four (fn [] #{5}))
lisp forms are simple
(def a-var “some value”)
(def a-fn (fn [a b] ,,, ))
(defn a-fn [a b] ,,, ) ; same!
lisp forms are uniform
(def turtle “ _,.---.---.---.--.._ _.-' `--.`---.`---'-. _,`--.._ /`--._ .'. `. `,`-.`-._\ || \ `.`---.__`__..-`. ,'`-._/ _ ,`\ `-._\ \ `. `_.-`-._,``-. ,` `-_ \/ `-.`--.\ _\_.-'\__.-`-.`-._`. (_.o> ,--. `._/'--.-`,--` \_.-' \`-._ \ `---' `._ `---._/__,----` `-. `-\ /_, , _..-' `-._\ \_, \/ ._( \_, \/ ._\ `._,\/ ._\ `._// ./`-._ `-._-_-_.-‘ ”)
all the way down
almost: special forms
• def
• var
• quote
• do
• if
• let
• fn
• loop/recur
• try/catch/finally/throw
… vs. JavaScript — 60 / 191 depending
“The first rule of Macro Club is Don’t Write Macros.”
Stu Halloway, Programming Clojure
macros are not simple
.js .cljs
var url = “http://…”; (def url “http://…”)
function hello(name) { console.log(“hello, ”+ name); }
(defn hello [name] (println “hello, ” name)
// got nothing (ns my.library (require [other.lib :as o))
var person = {first: “bob”, last: “smith”};
var first = person.first; var last = person.last;
// do stuff
var color = [128, 55, 55, 0.5]; var r = color[0]; var g = color[1]; var a = color[3];
// do stuff
(def person {:first “bob” :last “smith”})
(let [{:keys [first last]} person] ,,,)
(def color = [128 55 55 0.5])
(let [[r g _ a] color] ,,,)
[event f] (swap! state add-listener event f))
(def twitter-uri (goog.Uri. "http://search.twitter.com/search.json"))
(defn search-tag "Get the current tag value from the page." [] (.-value (dom/get-element :twitter-search-tag)))
(defn retrieve "Send request to twitter." [payload callback error-callback] (.send (goog.net.Jsonp. twitter-uri) payload callback error-callback))
(defn send-event "For the given event, call every listener for that event, passing the message." ([event] (send-event event nil)) ([event message] (doseq [f (-> @state :listeners event)] (f message))))
(defn parse-mentions "Given a map representing a single tweet, return all mentions that are found within the tweet text. Twitter usernames are not case sensitive so mentioned usernames are always returned in lower case."
docstring!
multi-dispatch!
everything is a list.
( ) > ; ?
meh. zealotry is not useful.
.cljs data types
• immutable
• persistent data structures
• performant
• lists ()
• vectors []
• hash-maps {}
• hash-sets #{}
;; hash-map, or ‘map’ (hash-map :a “eh” :b “bee” :c “see”) {:a “eh” :b “bee” :c “see”} ;; same
(def a-map {:a “eh” :b “bee”})
(get a-map :a) ;-> “eh” (:b a-map) ;-> “bee”
(assoc a-map :c “see”) ;-> {:a “eh” :b “bee” :c “see”}
hash-maps: keyed
;; vector (vector 1 2 “three” :four) [1 2 “three” :four] ;; same thing
(def a-vector [1 2 “three” :four])
(get a-vector 2) ;-> “three” (nth a-vector 3) ;-> :four
(conj a-vector ‘five) ;-> [1 2 “three” :four ‘five]
vectors: indexed
;; hash-set (hash-set 1 2 “three” :four) #{1 2 “three” :four} ;; same
;; hash-set is a map with no values (hash-map :a “eh” :b “bee”) {:a “eh” :b “bee”}
;; set can hold anything unique (hashset 1 two “three” #(:four))
hash-sets: unique, fast
Sequences : the fundamental abstraction.
• one element at a time • lazy, ∴ potentially infinite • all collection types are seqable • convert to/from with seq/into
sequences
(def nums [1 2 3 4 5]
(map #(* 2 %) nums) ; (2 4 6 8 10)
(reduce + nums) ; 15 (reduce + (map #(* 2 %) nums) ; 30
(filter odd? mums) ; (1 3 5) (remove odd? mums) ; (2 4)
sequence fns
(def nums [1 2 3 4 5]
(partition 2 nums) ; ((1 2) (3 4))
(take-while #(< 4) nums) ; (1 2 3)
;; for clarity (defn shift-once [n] (bit-shift-left n 1))
;; infinite, lazy (def twos (iterate shift-once 1)) (take 4 twos) ; (1 2 4 8 16)
more sequence fns
;; infinite, lazy, anonymous fn
(def twos (iterate (fn [n](bit-shift-left % 1)) 1))
(def twos* ;; with shortcut (iterate #(bit-shift-left % 1) 1))
(take 4 twos*) ; (1 2 4 8 16)
more sequence fns
;; destructuring a list - note, no return
(def color [255 100 175 0.6])
(defn rgb->hex “converts rgba notation to a hex string, dropping alpha” [[r g b _]] (str "#" (.toString r 16) (.toString g 16) (.toString b 16)))
(rgb->hex color) ; "#ff64af"
;; destructuring a map
(def color {:r 255 :g 100 :b 175 :a 0.6])
(defn rgb->hex “converts rgba notation to a hex string, dropping alpha” [{:keys [r g b]}] ;; maybe :as color (str "#" (.toString r 16) (.toString g 16) (.toString b 16)))
(rgb->hex color) ; "#ff64af"
;; a little more clojure-y
(defn rgb->hex “converts rgba notation to a hex string, dropping alpha” [rgba] (->> (take 3 rgba) (map #(.toString % 16)) (apply str “#”)))
(rgb->hex [255 100 175 0.6 0 0 0]) ; "#ff64af"
;; all the way clojure-y
(defn rgb->hex “converts rgba notation to a hex string, dropping alpha” [& rgbx] (->> (take 3 rgbx) (map #(.toString % 16)) (apply str “#”)))
(rgb->hex 255 100 175 0.6 0 0 0) ; "#ff64af"
Clojure/Script is very opinionated, and prefers lean,
expressive code.
which doesn’t matter at all; do what works for you.
quick start?
The tool chain needed to get to any particular starting place can be fiddly.
the docs?
When in doubt, David Nolen (@swannodette) will have the most current information.
• the actual coding experience
• concurrent processes with core.async and web workers
• developing in the REPL
• live updates with figwheel
things I wanted to get to today (i.e., part 2)
• core.logic (> mini-kanren)
• core.match
• test.check
• atoms, refs, and the unified update model
maybe next time.
questions?
fonts:
FFF Tusj Avenir Next Avenir Next Condensed Anonymous Pro
urls: http://clojure.org http://github.com/clojure/clojurescript http://swannodette.github.io/
Ben [email protected] / ben.vandgrift.com
(.log js/console “thanks!”)