Skip to content

Instantly share code, notes, and snippets.

@triclops200
Last active August 29, 2015 14:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save triclops200/5f1012efb71d41ffcb6a to your computer and use it in GitHub Desktop.
Save triclops200/5f1012efb71d41ffcb6a to your computer and use it in GitHub Desktop.
So far
;; gorilla-repl.fileformat = 1
;; **
;;; #Clojure Report
;; **
;; @@
(ns clojure-report.clojure-report
(:require [gorilla-plot.core :as plot])
(:require [clojure.core.typed :as t]))
;; @@
;; =>
;;; {"type":"html","content":"<span class='clj-nil'>nil</span>","value":"nil"}
;; <=
;; **
;;; ##History
;;;
;;; ###Important Times
;;; Clojure was developed over the course of two and a half years by Rich Hickey, and was released for public use in 2007. [1]
;;;
;;; ###Purpose
;;; The language was developed to solve a few major problems. The first was to create a modern lisp, a new take on "batteries included," not much unlike Common Lisp when that was created. The second was that he believes that functional languages are the future, and wanted to make a functional lisp. Closely related to this, he wanted to create a language designed for concurrency, which he achieved.[2] An example of some of the concurrent code is shown below.
;;; ####Example Concurrent Code
;; **
;; @@
(defn fib [x]
(loop [x x
a 0
b 1]
(if (= x 0)
a
(recur (dec x) b (+' a b)))))
(time (reduce +' (pmap fib (range 3000)))) ;; Executes map in paralell over all of the elements
(time (reduce +' (map fib (range 3000)))) ;; Standard single threaded map
;; @@
;; ->
;;; &quot;Elapsed time: 207.550825 msecs&quot;
;;; &quot;Elapsed time: 510.263049 msecs&quot;
;;;
;; <-
;; =>
;;; {"type":"html","content":"<span class='clj-bigint'>664390460366960072280217847866028384244163512452783259405579765542621214161219257396449810982999820391132226802809465132446349331994409434926019045342723749188530316994678473551320635101099619382973181622585687336939784373527897555489486841726131733814340129175622450421605101025897173235990662770203756438786517530547101123748849140252686120104032647025145598956675902135010566909783124959436469825558314289701354227151784602865710780624675107056569822820542846660321813838896275819753281371491809004412219124856375121694811728724213667814577326618521478357661859018967313354840178403197559969056510791709859144173304364898000N</span>","value":"664390460366960072280217847866028384244163512452783259405579765542621214161219257396449810982999820391132226802809465132446349331994409434926019045342723749188530316994678473551320635101099619382973181622585687336939784373527897555489486841726131733814340129175622450421605101025897173235990662770203756438786517530547101123748849140252686120104032647025145598956675902135010566909783124959436469825558314289701354227151784602865710780624675107056569822820542846660321813838896275819753281371491809004412219124856375121694811728724213667814577326618521478357661859018967313354840178403197559969056510791709859144173304364898000N"}
;; <=
;; **
;;; ###Toolchain
;;;
;;; Clojure is a JVM language. The language itself is compiled by the java compiler, and the source is actually availible [here](https://github.com/clojure/clojure).
;; **
;; **
;;; ##Characteristics
;;;
;;; Clojure is primarily a functional object oriented language which is both statically and dynamically compiled to bytecode which is then JITted by the JVM which runs it. The combination of static and dynamic compilation is a feature shared with most modern implementations of Common Lisp: functions known at compile time are compiled outright, but, closures and various anonymous functions are often compiled to some intermediate bytecode/native code before being run. In the case of Clojure, its bytecode is just JVM code.
;;; Another interesting feature to note is the fact that Clojure, like most lisps, is homoiconic, meaning that the same data structures that the user uses while programming is what the internal structure of the program is represented in. This allows for structural abstraction via code generation, but written in the same language that does the generation. This means that you can do turing complete computations in the compile step using the same functions that are being compiled. The result is that language extension is a natural part of the language, allowing major features to be added, modified, or removed as desired. [2]
;;;
;;;
;;; By default, clojure is a strongly dynamically typed language, meaning that a string is a string and not a number, but, it is unknown at compile time what the type is. However, the Core.Typed library adds static typing to the language. An example of the addition is shown below.
;;;
;;; ####Type example
;; **
;; @@
(first (:delayed-errors (t/check-form-info '(do ;;Ignore this line, just used to pretty print the errors to this repl
(t/ann add2 [t/Int -> t/Int]) ;; Sucessfully typed
(defn add2 [x]
(+ x 2))
(t/ann add3 [t/Int -> t/Str]) ;; Unsucessfully typed
(defn add3 [x]
(+ x 2))
))))
;; @@
;; ->
;;; Initializing core.typed ...
;;; Building core.typed base environments ...
;;; Finished building base environments
;;; &quot;Elapsed time: 7529.71306 msecs&quot;
;;; core.typed initialized.
;;;
;; <-
;; =>
;;; {"type":"html","content":"<span class='clj-unkown'>#&lt;ExceptionInfo clojure.lang.ExceptionInfo: Type mismatch:\n\nExpected: \tt/Str\n\nActual: \tt/AnyInteger {:env {:file &quot;/tmp/form-init237689961398053814.clj&quot;, :column 3, :line 10}, :form (clojure.lang.Numbers/add x 2), :type-error :clojure.core.typed.errors/tc-error-parent}&gt;</span>","value":"#<ExceptionInfo clojure.lang.ExceptionInfo: Type mismatch:\n\nExpected: \tt/Str\n\nActual: \tt/AnyInteger {:env {:file \"/tmp/form-init237689961398053814.clj\", :column 3, :line 10}, :form (clojure.lang.Numbers/add x 2), :type-error :clojure.core.typed.errors/tc-error-parent}>"}
;; <=
;; **
;;; The language is strict in evaluation, but does implement lazy sequneces, and, by default, the traditional functional language functions such as map, filter, and iterate return them.
;;;
;;; ####Lazy sequence example
;; **
;; @@
(take 100 (map (partial + 1) (range)))
;; @@
;; =>
;;; {"type":"list-like","open":"<span class='clj-lazy-seq'>(</span>","close":"<span class='clj-lazy-seq'>)</span>","separator":" ","items":[{"type":"html","content":"<span class='clj-long'>1</span>","value":"1"},{"type":"html","content":"<span class='clj-long'>2</span>","value":"2"},{"type":"html","content":"<span class='clj-long'>3</span>","value":"3"},{"type":"html","content":"<span class='clj-long'>4</span>","value":"4"},{"type":"html","content":"<span class='clj-long'>5</span>","value":"5"},{"type":"html","content":"<span class='clj-long'>6</span>","value":"6"},{"type":"html","content":"<span class='clj-long'>7</span>","value":"7"},{"type":"html","content":"<span class='clj-long'>8</span>","value":"8"},{"type":"html","content":"<span class='clj-long'>9</span>","value":"9"},{"type":"html","content":"<span class='clj-long'>10</span>","value":"10"},{"type":"html","content":"<span class='clj-long'>11</span>","value":"11"},{"type":"html","content":"<span class='clj-long'>12</span>","value":"12"},{"type":"html","content":"<span class='clj-long'>13</span>","value":"13"},{"type":"html","content":"<span class='clj-long'>14</span>","value":"14"},{"type":"html","content":"<span class='clj-long'>15</span>","value":"15"},{"type":"html","content":"<span class='clj-long'>16</span>","value":"16"},{"type":"html","content":"<span class='clj-long'>17</span>","value":"17"},{"type":"html","content":"<span class='clj-long'>18</span>","value":"18"},{"type":"html","content":"<span class='clj-long'>19</span>","value":"19"},{"type":"html","content":"<span class='clj-long'>20</span>","value":"20"},{"type":"html","content":"<span class='clj-long'>21</span>","value":"21"},{"type":"html","content":"<span class='clj-long'>22</span>","value":"22"},{"type":"html","content":"<span class='clj-long'>23</span>","value":"23"},{"type":"html","content":"<span class='clj-long'>24</span>","value":"24"},{"type":"html","content":"<span class='clj-long'>25</span>","value":"25"},{"type":"html","content":"<span class='clj-long'>26</span>","value":"26"},{"type":"html","content":"<span class='clj-long'>27</span>","value":"27"},{"type":"html","content":"<span class='clj-long'>28</span>","value":"28"},{"type":"html","content":"<span class='clj-long'>29</span>","value":"29"},{"type":"html","content":"<span class='clj-long'>30</span>","value":"30"},{"type":"html","content":"<span class='clj-long'>31</span>","value":"31"},{"type":"html","content":"<span class='clj-long'>32</span>","value":"32"},{"type":"html","content":"<span class='clj-long'>33</span>","value":"33"},{"type":"html","content":"<span class='clj-long'>34</span>","value":"34"},{"type":"html","content":"<span class='clj-long'>35</span>","value":"35"},{"type":"html","content":"<span class='clj-long'>36</span>","value":"36"},{"type":"html","content":"<span class='clj-long'>37</span>","value":"37"},{"type":"html","content":"<span class='clj-long'>38</span>","value":"38"},{"type":"html","content":"<span class='clj-long'>39</span>","value":"39"},{"type":"html","content":"<span class='clj-long'>40</span>","value":"40"},{"type":"html","content":"<span class='clj-long'>41</span>","value":"41"},{"type":"html","content":"<span class='clj-long'>42</span>","value":"42"},{"type":"html","content":"<span class='clj-long'>43</span>","value":"43"},{"type":"html","content":"<span class='clj-long'>44</span>","value":"44"},{"type":"html","content":"<span class='clj-long'>45</span>","value":"45"},{"type":"html","content":"<span class='clj-long'>46</span>","value":"46"},{"type":"html","content":"<span class='clj-long'>47</span>","value":"47"},{"type":"html","content":"<span class='clj-long'>48</span>","value":"48"},{"type":"html","content":"<span class='clj-long'>49</span>","value":"49"},{"type":"html","content":"<span class='clj-long'>50</span>","value":"50"},{"type":"html","content":"<span class='clj-long'>51</span>","value":"51"},{"type":"html","content":"<span class='clj-long'>52</span>","value":"52"},{"type":"html","content":"<span class='clj-long'>53</span>","value":"53"},{"type":"html","content":"<span class='clj-long'>54</span>","value":"54"},{"type":"html","content":"<span class='clj-long'>55</span>","value":"55"},{"type":"html","content":"<span class='clj-long'>56</span>","value":"56"},{"type":"html","content":"<span class='clj-long'>57</span>","value":"57"},{"type":"html","content":"<span class='clj-long'>58</span>","value":"58"},{"type":"html","content":"<span class='clj-long'>59</span>","value":"59"},{"type":"html","content":"<span class='clj-long'>60</span>","value":"60"},{"type":"html","content":"<span class='clj-long'>61</span>","value":"61"},{"type":"html","content":"<span class='clj-long'>62</span>","value":"62"},{"type":"html","content":"<span class='clj-long'>63</span>","value":"63"},{"type":"html","content":"<span class='clj-long'>64</span>","value":"64"},{"type":"html","content":"<span class='clj-long'>65</span>","value":"65"},{"type":"html","content":"<span class='clj-long'>66</span>","value":"66"},{"type":"html","content":"<span class='clj-long'>67</span>","value":"67"},{"type":"html","content":"<span class='clj-long'>68</span>","value":"68"},{"type":"html","content":"<span class='clj-long'>69</span>","value":"69"},{"type":"html","content":"<span class='clj-long'>70</span>","value":"70"},{"type":"html","content":"<span class='clj-long'>71</span>","value":"71"},{"type":"html","content":"<span class='clj-long'>72</span>","value":"72"},{"type":"html","content":"<span class='clj-long'>73</span>","value":"73"},{"type":"html","content":"<span class='clj-long'>74</span>","value":"74"},{"type":"html","content":"<span class='clj-long'>75</span>","value":"75"},{"type":"html","content":"<span class='clj-long'>76</span>","value":"76"},{"type":"html","content":"<span class='clj-long'>77</span>","value":"77"},{"type":"html","content":"<span class='clj-long'>78</span>","value":"78"},{"type":"html","content":"<span class='clj-long'>79</span>","value":"79"},{"type":"html","content":"<span class='clj-long'>80</span>","value":"80"},{"type":"html","content":"<span class='clj-long'>81</span>","value":"81"},{"type":"html","content":"<span class='clj-long'>82</span>","value":"82"},{"type":"html","content":"<span class='clj-long'>83</span>","value":"83"},{"type":"html","content":"<span class='clj-long'>84</span>","value":"84"},{"type":"html","content":"<span class='clj-long'>85</span>","value":"85"},{"type":"html","content":"<span class='clj-long'>86</span>","value":"86"},{"type":"html","content":"<span class='clj-long'>87</span>","value":"87"},{"type":"html","content":"<span class='clj-long'>88</span>","value":"88"},{"type":"html","content":"<span class='clj-long'>89</span>","value":"89"},{"type":"html","content":"<span class='clj-long'>90</span>","value":"90"},{"type":"html","content":"<span class='clj-long'>91</span>","value":"91"},{"type":"html","content":"<span class='clj-long'>92</span>","value":"92"},{"type":"html","content":"<span class='clj-long'>93</span>","value":"93"},{"type":"html","content":"<span class='clj-long'>94</span>","value":"94"},{"type":"html","content":"<span class='clj-long'>95</span>","value":"95"},{"type":"html","content":"<span class='clj-long'>96</span>","value":"96"},{"type":"html","content":"<span class='clj-long'>97</span>","value":"97"},{"type":"html","content":"<span class='clj-long'>98</span>","value":"98"},{"type":"html","content":"<span class='clj-long'>99</span>","value":"99"},{"type":"html","content":"<span class='clj-long'>100</span>","value":"100"}],"value":"(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100)"}
;; <=
;; **
;;;
;;; ####Scoping
;;; The scoping rules are fully lexical (static) with support for closures.
;;;
;;; ####Parameters
;;; Parameter passing is variadic by position with support for keyword arguments and pattern matching over certain datastructures. Clojure also allows, via the apply function, to call functions with sequences as if the sequence contained the arguments to the function.
;;;
;;;
;;; ####Abstract Data Types
;;; Clojure fully interfaces with java interfaces and supports ad-hoc polymorphism as well as something called multimethods. These are seperate from java interfaces, but are much more dynamic as they support dispatch over generic values. Mulitmethods take in a value and do a transformation to it. They then pattern match over the transformed value to call the appropriate method. An example is shown below.
;; **
;; @@
(defmulti area ;;Define the method name
(fn [shape] ;;This function is the key function that transforms the shape value to the key
(get shape :type)))
(defmethod area :rectangle [shape] ;;This matches any value that the key function returned :rectangle
(* (:width shape) (:height shape)))
(defmethod area :circle [shape]
(* (:radius shape) (:radius shape) (. Math PI)))
(def rect {:type :rectangle, :width 2, :height 8})
(def circ {:type :circle, :radius 2})
(println (area rect))
(println (area circ))
;; @@
;; ->
;;; 16
;;; 12.566370614359172
;;;
;; <-
;; =>
;;; {"type":"html","content":"<span class='clj-nil'>nil</span>","value":"nil"}
;; <=
;; **
;;; ####Homoiconicity
;;;
;;; Clojure, like most lisps, is a fully homoiconic language. As mentioned above, that means that the AST data structures are the same as what the developer uses to update. This means you can define new language features. An example of adding syntax to define memoized functions is shown below.
;; **
;; @@
(defmacro defmem [name parms & body]
(let [fname (gensym) memname (gensym)]
`(do (declare ~name)
(letfn [(~fname ~parms ~@body)]
(let [~memname (atom {})]
(defn ~name ~parms
(if (contains? @~memname ~parms)
(get @~memname ~parms)
(do (swap! ~memname assoc ~parms (~fname ~@parms))
(get @~memname ~parms))))))))) ;; This adds the defmem feature to clojure
(defmem memo-fib [x]
(if (<= x 1)
x
(+ (memo-fib (- x 1)) (memo-fib (- x 2))))) ;; The code between this and the slow fib is exactly the same with defmem instead of defn, but is fully memoized
(defn slow-fib [x]
(if (<= x 1)
x
(+ (slow-fib (- x 1)) (slow-fib (- x 2)))))
(time (memo-fib 30))
(time (slow-fib 30))
;; @@
;; ->
;;; &quot;Elapsed time: 0.806034 msecs&quot;
;;; &quot;Elapsed time: 85.699549 msecs&quot;
;;;
;; <-
;; =>
;;; {"type":"html","content":"<span class='clj-long'>832040</span>","value":"832040"}
;; <=
;; **
;;; ####Java Integration
;;;
;;; Clojure is fully integrated with java, which means that I can use java libraries and code if there is nothing availible for Clojure or performance is a concern.
;; **
;; @@
(def array-list
(doto (java.util.ArrayList.)
(.add 1)
(.add 2)
(.add 3)))
(println (.get array-list 2))
(println array-list)
;; @@
;; ->
;;; 3
;;; #&lt;ArrayList [1, 2, 3]&gt;
;;;
;; <-
;; =>
;;; {"type":"html","content":"<span class='clj-nil'>nil</span>","value":"nil"}
;; <=
;; **
;;; ##Examples
;;;
;;;
;;;
;;; ###Hello World
;; **
;; @@
(println "Hello World!")
;; @@
;; ->
;;; Hello World!
;;;
;; <-
;; =>
;;; {"type":"html","content":"<span class='clj-nil'>nil</span>","value":"nil"}
;; <=
;; **
;;; ###QuickSort
;; **
;; @@
(defn size-partition [x xs]
(let [res (group-by (partial < x) xs)]
[(get res false) (get res true)]))
(defn quick-sort [xs]
(if (empty? xs)
xs
(let [x (first xs)
xs (rest xs)
[lt gt] (size-partition x xs)]
(concat (quick-sort lt) [x] (quick-sort gt)))))
(println (quick-sort [2 3 1 4 5 0]))
;; @@
;; ->
;;; (0 1 2 3 4 5)
;;;
;; <-
;; =>
;;; {"type":"html","content":"<span class='clj-nil'>nil</span>","value":"nil"}
;; <=
;; **
;;; ###Sum a list of ints from a file
;; **
;; @@
(def url "https://gist.githubusercontent.com/triclops200/41c0a104d66fc8da3adb/raw/826572439a57e79aa54d96c94681900fa63ed1cd/sampleinput")
(let [split-text
(-> (slurp url) ;; download text file from url; it really is that easy
(clojure.string/split #"\s+"))] ;; split the string by whitespace
(reduce + (map #(Integer/parseInt %) split-text))) ;; parse the integers and sum them up
;; @@
;; =>
;;; {"type":"html","content":"<span class='clj-long'>451</span>","value":"451"}
;; <=
;; **
;;; ## Why I chose Clojure
;;;
;;; I chose Clojure because, at the time, I was using Common Lisp, but was frustrated at the fact that it wasn't a LISP-1 (which means that Common Lisp has seperate namespaces for variables and functions), and the lack of good threading and sockets. Clojure is a modern language that has basically all the powerful meta-programming features that Common Lisp has (minus custom reader macros, but there is a lot of good reasoning for that), but is batteries included when it comes to functional progamming and modern features. I continue to use it due to the power and the huge selection of libraries. It is by far my favorite language and I've even used it professionally by convincing a manager of its redeeming features over Java.
;;;
;; **
;; **
;;; ## References
;;;
;;;
;;; [1] http://codequarterly.com/2011/rich-hickey/
;;;
;;;
;;; [2] http://clojure.org/rationale
;; **
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment