# Clojure for Pythonistas & Data Scientists ## Why care? #### Hello World ```python print("Hello World!") ``` ```clojure (println "Hello World!") ``` #### Numbers ```python num = 7 print(num) flt = 7.2 print(flt) flt = float(7) print(flt) ``` ```clojure (def num 7) (println num) (def flt 7.2) (println flt) (def flt (float 7)) (println flt) ``` #### Strings ```python word = 'hello' print(word) word = "hello" ``` ```clojure (def word "hello") (println word) ``` #### Math ```python 1 + 2 * 3 / 4 ``` ```clojure (+ 1 (/ (* 2 3) 4)) ``` ```python 11 % 3 ``` ```clojure (mod 11 3) ``` ```python 7 ** 2 ``` ```clojure (Math/pow 7 2) ; or (defn ** [x n] (reduce * (repeat n x))) (** 7 2) ``` ```python "hello" + " " + "world" ``` ```clojure (str "hello" " " "world") ``` #### Data structures ```python [1, 2, 3] mylist = [] mylist.append(1) mylist.append(2) mylist.append(3) print(mylist) ``` ```clojure [1 2 3] (def mylist []) (conj mylist 1) (conj mylist 2) (conj mylist 3) (println mylist) ``` ```python mylist = [1, 2, 3] # get first element mylist[0] # get last element mylist[-1] # get a range mylist[:1] # count len(mylist) ``` ```clojure (def mylist [1 2 3]) # get first element (first mylist) (get mylist 0) (mylist 0) (nth mylist 0) # get last element (last mylist) (peek mylist) # get a range (take 2 mylist) # count (count mylist) ``` ```python phonebook = { "John" : 938477566, "Jack" : 938377264, "Jill" : 947662781 } print(phonebook) ``` ```clojure (def phonebook {:john 938477566 :jack 938377264 :jill 947662781}) (println phonebook) ``` ```python phonebook["John"] phonebook["Alex"] = 999555789 print(phonebook) phonebook["John"] = phonebook["John"] + 1 phonebook.pop("John") print(phonebook) ``` ```clojure (phonebook :john) (:john phonebook) (get phonebook :john) (assoc phonebook "Alex" 999555789) (println phonebook) (def phonebook (assoc phonebook "Alex" 999555789)) (get phonebook "Alex") (phonebook "Alex") (update phonebook :john inc) (dissoc phonebook :john) ``` #### String operations ```python len("Hello") ``` ```clojure (count "hello") (.length "hello") ``` ```python "string".index("n") ``` ```clojure (.indexOf "string" "n") (clojure.string/index-of "string" "n") ``` ```python "hello".count("l") ``` ```clojure (frequencies "hello") (get (frequencies "hello") \l) ``` ```python "Hello world!"[3:7] ``` ```clojure (subs "Hello world!" 3 7) ``` ```python "abc".upper() "ABC".lower() ``` ```clojure (clojure.string/upper-case "abc") (.toUpperCase "abc") (clojure.string/lower-case "ABC") (.toLowerCase "ABC") ``` ```python "hey there".split(" ") ``` ```clojure (clojure.string/split "hey there" #" ") ``` #### Conditions ```python x = 2 x == 2 # True x == 3 # False x < 3 # True ``` ```clojure (def x 2) (= x 2) ; true (= x 3) ; false (< x 3) ; true ``` ```python name = "John" age = 23 if name == "John" and age == 23: print("Your name is John, and you are also 23 years old.") if name == "John" or name == "Rick": print("Your name is either John or Rick.") ``` ```clojure (def nme "John") (def age 23) (if (and (= nme "John") (= age 23)) (println "Your name is John, and you are also 23 years old.")) (if (or (= nme "John") (= nme "Rick") (println "Your name is John, and you are also 23 years old.")) (when (and (= nme "John") (= age 23)) (println "Your name is John, and you are also 23 years old.")) (case nme "John" :john "Rick" :rick :who?) (cond (< age 18) "You can't drink for sure" (<= 18 age 21) "Somewhere you can drink, somewhere you can't" "Have fun drinking (not too much)!") ``` ```python name = "John" if name in ["John", "Rick"]: print("Your name is either John or Rick.") ``` ```clojure (def nme "John") (when (some #{"John" "Rick"} nme) (println "Your name is either John or Rick.")) ``` ```python x = [1,2,3] y = [1,2,3] print(x == y) # True print(x is y) # False ``` ```clojure (def x [1 2 3]) (def y [1 2 3]) (= x y) ; true (identical? x y) ; false ``` ```python not False # True ``` ```clojure (not false) (if-not true 1 0) (when-not true (println "This won't print")) ``` #### Loops & co. ```python primes = [2, 3, 5, 7] for prime in primes: print(prime + 1) [p + 1 for p in primes] numbers = list(range(100)) [n for n in numbers if n % 2 == 0] list(filter(lambda x: (x % 2 == 0), numbers)) ``` ```clojure (def primes [2 3 5 7]) (for [p primes] (inc p)) (map inc primes) (loop [f (first primes) r (rest primes) res []] (if f (recur (first r) (rest r) (conj res (inc f))) res)) (filter even? (range 100)) ``` #### Functions ```python def my_function(): print("Hello there!") ``` ```clojure (defn my-function (println "Hello there!")) ``` ```python def my_function_with_args(username, greeting): print("Hello, %s, I wish you %s" % (username, greeting)) ``` ```clojure (defn my-function-with-args [username greeting] (println "Hello," username ", I wish you" greeting)) ``` ```python def sum_two_numbers(a, b): return a + b ``` ```clojure (defn sum-2-numbers [a b] (+ a b)) ``` #### Laziness ```python range(10) list(range(10)) ``` ```clojure (range 10) (->> (range) (take 10) (map inc) (filter even?)) ``` ```python import random def lottery(): # returns 6 numbers between 1 and 40 for i in range(6): yield random.randint(1, 40) # returns a 7th number between 1 and 15 yield random.randint(1,15) for random_number in lottery(): print("And the next number is... %d!" %(random_number)) ``` ```clojure (defn lottery [] (let [a (for [i (range 6)] (inc (rand-int 40))) b (inc (rand-int 15))] (concat a [b]))) (defn random-generator [n] (inc (rand-int n))) (defn random-numbers [n] (repeatedly #(random-generator n))) (defn lottery [] (let [a (take 6 (random-numbers 40)) b (take 1 (random-numbers 15))] (flatten [a b]))) (doseq [l (lottery)] (println "And the next number is..." l)) (def lottery (let [n (atom 0)] (repeatedly (fn [] (swap! n inc) (if (zero? (mod @n 6)) (inc (rand-int 15)) (inc (rand-int 40))))))) (doseq [l (take 6 lottery)] (println "And the next number is..." l)) ```