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"))