(take 4 (range 10000))
(+ 1 2 3 4)
s-exp
is called an atomCalling a function in JavaScript
funName(arg1, arg2, arg3);
Calling a function in Clojure
(fun-name arg1 arg2 arg3)
Defining variables in JavaScript
var now = new Date();
Defining variables in Clojure
(def now (Date.))
Calling instance methods in JavaScript or Java
now.getDay();
Calling JavaScript or Java instance methods in Clojure
(.getDay now) ;; call a method without arguments
Calling a static method in JavaScript or Java
Date.parse("March 21, 2012");
Calling a static JavaScript or Java method in Clojure
(Date/parse "March 21, 2012") ;; 1332302400000
Defining a function in JavaScript
var add10 = function (x) { return x + 10; };
function add10(x) { return x + 10; };
Defining a function in Clojure
(fn [x] (- 20 x)
(def add10 (fn [x] (+ 10 x)))
(defn add10 [x] (+ 10 x))
(add10 -4) ;; 6
Taking variable arguments in a function
var reduce_PLUS = function () {
var args = Array.prototype.slice.call(arguments);
return plus.apply(this, args);
};
reduce_PLUS(1, 2, 3); // 6
(defn reduce+ [& args] (apply + args))
(reduce+ 1 2 3) ;; 6
(defn argcount
([] 0)
([x] 1)
([x y] 2)
([x y & more] (+ (argcount x y) (count more))))
From util.math
(defn round [x precision]
(MathUtils/round x precision))
(round 5.5 0) ;; 6.0
From util.time
(defn get-requested-at [typed-data]
(SystemTimeFactory/getMillis
(.getRequestedAt typed-data)))
From util.cascalog
(defn within-window?
"True if t2 between t1 and a window amount of time
after t1."
[t1 window t2]
(and
(< t1 t2)
(< t2 (+ t1 window))))
(within-window? 3 1 3.9) ;; true
(within-window? 3 1 4) ;; false
a.clj
(ns a
(:import [java Math]))
(def var "10")
(defn parse-int [x]
(when-not (integer? x)
(Integer/parseInt x)))
b.clj
(ns b
(:use [a])
(:use [a :only (parse-int)])
(:require [a :as utils]))
(utils/parse-int "10")
(utils/parse-int 10)
(1 2)
[1 2]
#{1 2}
{:a 1}
strings "string"
(only some seq functions work on strings)
Collections in clojure are polymorphic
(def a [1 "string" :keyword {:key "value"}])
(def a {:a 1 :b "number"})
polymorphic
. That is they
operate on different types of collections. For example,(conj [] :a) ;; [:a]
(conj {:a 1} [:b 2]) ;; {:b 2, :a 1}
(conj #{:a} :b) ;; #{:a :b}
Add doall
to evaluate an expression
From extract.signals-test
(doall (map
signals-tests-for-site
[SiteType/SITE1
SiteType/SITE2
SiteType/SITE3
SiteType/SITE4]))
(def a [1 2 3])
(def b (conj 0 a))
(= a [1 2 3]) ;; true
(= b [0 1 2 3]) ;; true
vector
(def a [1 2 3]) ;; create
(cons 1 []) ;; '(1)
(cons 1 [2 3]) ;; '(1 2 3)
(count a) ;; 3
(first a) ;; 1
(second a) ;; 2
(rest a) ;; [2 3]
(contains? [1 2 3] 0) ;; true
(contains? [1 2 3] 3) ;; false
(a 0) ;; 1
(get a 1) ;; 2
(get a 10 :default) ;; :default
(nth a 1) ;; 2
(nth a 10) ;; throw IndexOutOfBoundsException
hash-map
A collection of key value pairs
(def ivan {:name "Ivan Willig"
:age 28
:address "360 Adams Street"})
(count ivan) ;; 3
(keys ivan) ;; (:age :name :address)
(vals ivan) ;; (28 "Ivan Willig" "360 Adams Street")
(:name ivan) ;; "Ivan Willig"
(:age ivan) ;; 28
(contains? ivan :name) ;; true
hash-map
(get ivan :name) ;; "Ivan Willig"
(get ivan :sane? "No !!!") ;; "No !!!"
(assoc ivan :mood "good")
;; {:age 28, :name "Ivan Willig", :mood "Good",
;; :address "360 Adams Street"}
(conj ivan ["mood" "good"])
;; {:age 28, :name "Ivan Willig", "mood" "good",
;; :address "360 Adams Street"}
(println ivan)
;; {:age 28, :name "Ivan Willig", :address "360 Adams Street"}
set
A collection of distinct elements
(require '[clojure.set :as s])
(def a #{1 2 3 4 5})
(def b #{2 3 4})
(def c #{6 7 8 9 10})
(s/subset? b a) ;; true
(s/union a c) ;; #{1 2 3 4 5 6 7 8 9 10}
(s/select integer? #{1 2 3 :a :b :c}) ;; #{1 2 3}
map, reduce, filter
(map inc [1 2 3 4 5])
;; (2 3 4 5 6)
(reduce + [1 2 3 4 5])
;; 15
(reduce + 10 [1 2 3 4 5])
;; 25)
(filter (fn [x] (< x 10)) [1 2 3 10 23 45])
;; (1 2 3)
(doseq [i [1 2 3]] (println i))
;; 1
;; 2
;; 3
;; 4
;; nil
(for [i [1 2 3 4 5]] (* 3 i))
;; (3 6 9 12 15)
(doseq [[key value] {:a 1 :b 2 :c 3 :d 4}]
(println key)
(println "---")
(println value))
;; :a
;; ---
;; 1
([1 2 3 4] 0) ;; 1
(#{1 2 3 4} 0) ;; nil
(#{1 2 3 4} 1) ;; 1 ??? why
({:name "thing"} :name) ;; "thing"
Define a new type in JavaScript
var Point = function (x, y) {
this.x = x;
this.y = y;
};
Define a new type in Clojure
(defrecord Point [x y])
(def p (Point. 10 5))
(print (:x p)) ;; 10
(print (:y p)) ;; 5
defrecord
(defrecord Person [name age address])
(def dude (Person. "John Smith" 35 "1234 Ave E"))
(:name dude) ;; "John Smith"
(= dude (Person. "John Smith" 35 "1234 Ave E")) ;; true
defrecord
implements the following Clojure and Java interfaces
clojure.lang.IObj
clojure.lang.ILookup
clojure.lang.IKeywordLookup
clojure.lang.IPersistentMap
java.util.Map
java.io.Serializable
deftype
(deftype Person [name age address])
(def dude (Person. "John Smith" 35 "1234 Ave E"))
(.name dude) ;; "John Smith"
Extending existing types in JavaScript
Point.prototype.distance = function (other) {
var dx = this.x - other.x,
dy = this.y - other.y;
return Math.sqrt(dx * dx + dy * dy);
};
Point
can also be a Java type(defprotocol IDistance
(distance [self other]))
(extend-type Point
IDistance
(distance [self other]
(let [dx (- (:x self) (:x other))
dy (- (:y self) (:y other))]
(Math/sqrt (+ (* dx dx)
(* dy dy))))))
(def p0 (Point. 3 10))
(def p1 (Point. 6 6))
(distance p0 p1) ;; 5.0
(distance {:x 10 :y 10} p0) ;; throws
;; IllegalArgumentException
(distance p0 {:x 10 :y 10}) ;; 5.0
When we suspend evaluation we can work with the raw source code as a Lisp tree. All code can be thought of as a tree.
(* (+ 2 (* 4 6))
(+ 3 5 7))
s-expr
(defn unless' [expr then] (if (not expr) then nil))
(unless' false (println "should not run"))
;; should not run
(defmacro unless [expr then] `(if (not ~expr) ~then nil))
(unless false (println "should not run"))
;; nil
(defn unless2 [expr form] (if (not expr) nil (form)))
(unless2 false (fn [] (println "should not run")))
(defmacro if-not
([test then] `(if-not ~test ~then nil))
([test then else]
`(if (not ~test) ~then ~else)))
(defmacro when
[test & body]
(list 'if test (cons 'do body)))
(defmacro when-not
[test & body]
(list 'if test nil (cons 'do body)))
(macroexpand '(when-not true false))
;; (if true nil (do false))
(macroexpand-1 '(when true (println "hello world")))
;; (if true (do (println "hello world"))
eval
. Errors from eval
are runtime(defmacro thing [x] (list 'if x x)) ;; silly example
(macroexpand '(thing 10)
;; (macroexpand '(thing false))
(map thing '(true false 10 "Hello")) ;; throws CompilerException
From math.model-metrics
(defn- regression [betas signals]
(dot-product (cons 1 signals) betas))
(defn- logistic-regression
"Compute 1/(1 + e^(-regression(beta, signals)))."
[beta signals]
(/ 1
(+ 1
(Math/exp (- (regression beta signals))))))
(defn- make-predictions
[signals betas forecast]
(forecast betas signals))
forecast
function as an argument(make-predictions signals betas regression)
(make-predictions signals betas logistic-regression)
From extract.signals
(defn sites->features[site-type]
(sort-by (fn [x] (.name x))
(concat generic-features
(specific-features site-type))))
Abstract structural bindings
(def point [5 7])
(let [[x y] point]
(println "x:" x " y:" y)) ;; x: 5 y: 7
(def point {:x 5 :y 7})
(let [{x :x y :y} point]
(println "x:" x "y:" y)) ;; x: 5 y: 7
(let [{:keys [x y]} point]
(println "x:" x "y:" y)) ;; x: 5 y: 7
(defn -main [& args]
(let [arg-map (parse-args args)
{:keys [-stepInputBaseUrl
-outputUrl
-testingDateFrom
-testingDateTo
-trainingDateFrom
-trainingDateTo
-siteType
-productCategoryType
-publisherType
-dataType]} arg-map
base-input-path (UrlHelper/decode -stepInputBaseUrl)
output-path (UrlHelper/decode -outputUrl)
publisher-type (PublisherType/valueOf -publisherType)
site-type (SiteType/valueOf -siteType)]
;; some method call
))