by niquola DevConf 2014
@ waveaccess/choice-hospital-systems
Ruby is a language designed in the following steps: * take a simple lisp language (like one prior to CL). * remove macros, s-expression. * add simple object system (much simpler than CLOS). * add blocks, inspired by higher order functions. * add methods found in Smalltalk. * add functionality found in Perl (in OO way). So, Ruby was a Lisp originally, in theory. Let's call it MatzLisp from now on. ;-)
lisp is worth learning for the profound enlightenment experience you will have when you finally get it; that experience will make you a better programmer for the rest of your days, even if you never actually use Lisp itself a lot. Eric Raymond
(A LISP for Functional Programming on JVM designed for Concurency by Rich Hickey)
nil "string" 100.0 ;; number :keyword symbol (this is the list) [:this :is :the :vector] {:i "am", :the "Map"} #{\s \e \t}
(def symbol init?) (if test then else?) (do exprs*) (let [bindings* ] exprs*) (quote form) (var symbol) (fn name? [params* ] exprs*) (loop [bindings* ] exprs*) (recur exprs*) (throw expr) (try expr* catch-clause* finally-clause?)
[{:name "admin" :roles #{:admin}} {:name "user" :roles #{:author}}]
a + b*3
[:function, :myfn, [:x, :y], [:+, [:*, :x, :x], [:*, :y, :y]]] [:myfn, 3, 6]
[function myfn [x y] [+ [* x x] [* y y]]] [myfn 3 6]
(defn myfn [x y] (+ (* x x) (* y y))) (myfn 3 6)
function myfn(x,y){ //4 return x*x + y*y; //2 }; //2 myfn(3,6); //4 // sum: 12
(class module method statements ...) (only s-expression! )
form = (op arg arg) arg = form | data
(built-in-form) (function-call args list) (macros-call args and forms)
(defn f-name [args] body) (cond (pred1) (expr1) (pred2) (expr2)) (for [x xs] body)
(defmacro unless [pred f1 f2] (list 'if (list 'not pred) f1 f2)) (defmacro unless [pred f1 f2] `(if (not (~pred)) f1 f2)) (unless (= 1 2) (print "ok") (print "not"))
(constructor ...) => tp (selector tp) => ... (operations tp) => ...
collection = array collection = set collection.add(element)
| type | op1 | op2 | ? | | ------ |:----:| ----:| | | tp1 | x | x | | | tp2 | x | x | | | tp3 | x | x | | -> ?
(defprotocol Speaker (say [this])) (deftype Rubist [name age city] Speaker (say [this] (str "Hello i'm ruby"))) (deftype Javoid [name age city] Speaker (say [this] (str "Hello i'm java")))
(defmulti encounter (fn [x y] [(:Species x) (:Species y)])) (defmethod encounter [:Bunny :Lion] [b l] :run-away) (defmethod encounter [:Bunny :Bunny] [b l] :sex)
An Introduction to Functional Programming Through Lambda Calculus
Models need identity for the same reasons humans need identity - to represent the world.
a = 42 b = a a = a + 1 b = ?
a = [1] b = a a = concat(a, 1) b = ?
Calculate values functionaly
Use Refs & Agents for identity
(def my-atom (atom 0)) @my-atom (swap! my-atom inc)
Immutability makes much of the problem go away
Software Transactional Memory & agent systems
do the hard part
(use 'clojure.walk) (def thing {:page/tags [{:tag/category "lslsls"}]}) (postwalk #(if(keyword? %) (keyword (name %)) %) thing) => {:tags [{:category "lslsls"}]}
(let [[a b] [1 2] {meth :request-method} req {:keys [x y] :or {x 0 y 0}} point] ...)
(fact "here desc" (+ 1 2) => 3 (conj [1] 2) => (contains 1 2))
(def ch (chan)) (go (while true (let [v (<! ch)] (println "Read: " v)))) (go (>! ch "hi") (<! (timeout 5000)) (>! ch "there"))
(defentity users) (select users (where {:active true}) (order :created) (limit 5) (offset 3))
(def model [($in :x 1 6) ($in :y 3 7) ($= ($+ :x :y) 10)]) (solutions model) ;=> ({:y 7, :x 3} {:y 6, :x 4}...
(run* [q] (fresh [x y] (== [x 2] [1 y]) (== q [x y]))) ;=> ([1 2])
(require '[clojure.core.typed :refer [ann]]) (ann bar [Number -> Number]) (defn bar [b] (+ 2 (foo b)))
nREPL server started on port 49222 on host 127.0.0.1 user=> ...
(.toUpperCase "fred") (System/getProperty "java.vm.version") (.. System (getProperties) (get "os.name"))