(clj ♥)

Konrad Scorciapino

@konr

Diversão

  • Linguagem
  • DB

Clojure

(((((()))))))

;; 3 + 4
(+ 3 4) 

;; format("Olá, %s", joaozinho)
(format "Olá, %s" joãozinho)

Exemplo do Rosetta

function running_stddev() {
    var n = 0;
    var sum = 0.0;
    var sum_sq = 0.0;
    return function(num) {
        n++;
        sum += num;
        sum_sq += num*num;
        return Math.sqrt( (sum_sq / n) - Math.pow(sum / n, 2) );
    }
}
 
var sd = running_stddev();
var nums = [2,4,4,4,5,5,7,9];
var stddev = [];
for (var i in nums) 
    stddev.push( sd(nums[i]) );
 
// using WSH
WScript.Echo(stddev.join(', ');
(defn std-dev [samples]
  (let [n (count samples)
	mean (/ (reduce + samples) n)
	intermediate (map #(Math/pow (- %1 mean) 2) samples)]
    (Math/sqrt 
     (/ (reduce + intermediate) n))))    

Algo mais bonito

(defn effective-date [date]
  (find-first working-day? (dates-from date)))

Datalog

  • José está em São Paulo, agora, 24/05/2014
  • José está em Curitiba,    agora, 24/05/2015

Queries

  • Quem? está em São Paulo, agora, 24/05/2014
  • João o que? em São Paulo, agora, 24/05/2014
  • João      está onde?, agora, 24/05/2014
  • Quem? está onde?, agora, 24/05/2014
  • João está em São Paulo, agora, quando?
  • João não está mais em São Paulo quando?

Philosophia

  • Simplicidade
  • Immutabilidade
  • Programmabilidade

Immutabilidade

Copiar defensivamente

;; queue-out

(defn to-analysis-queue [user payment]
   (enqueue :analysis 
     {:user user
      :payment (assoc payment :processing-time (now))}))

(defn to-repayments-queue [user payment]
   (enqueue :repayments
     {:user (assoc user :repayment-account (get-repayment-account user))
      :repayment payment})


;; controller, sharing `purchase`

(defn new-payment [...]
  ...
  (when ... (queue/to-analysis-queue   user payment))
  (when ... (queue/to-repayments-queue user payment))
  payment)

Saber de mudanças

  • React - Javascript
  • DOM virtual
  • shouldComponentUpdate (ref vs alg)

Dados specificos no BD

  • Novos posts num aggregador de noticias
  • Dados pertencentes a um só usuário
  • Dados conhecidos numa certa data
;; (db)
[blog-1 :escreveu post-1 2014-05-24]
[blog-2 :escreveu post-1 2014-05-25]
[blog-4 :escreveu post-1 2014-05-25]
[blog-1 :escreveu post-1 2014-05-26]
[blog-3 :escreveu post-1 2014-05-26]
[blog-2 :escreveu post-1 2014-05-27]
[blog-2 :escreveu post-1 2014-05-27]
[blog-1 :escreveu post-1 2014-05-27]
[blog-1 :escreveu post-1 2014-05-28]


;; (since (db) 2014-05-28)
[blog-1 :escreveu post-1 2014-05-28]

;;(db)
[joão :nome "João da Silva" ...]
[joão  :id "deadbeef-1337" ...]
[pedro :id "deadbeef-4242" ...]
[pedro :nome "Pedro Parmeggiano" ...]
[joão :personagem "legolas.1234" ...]
[joão :personagem "konata_kawaii" ...]
[pedro :personagem "geronimo"]


;;(filter (db) (owner? "deadbeef-1337"))
[joão :nome "João da Silva" ...]
[joão  :id "deadbeef-1337" ...]
[joão :personagem "legolas.1234" ...]
[joão :personagem "konata_kawaii" ...]
;; (db)

[motor :consumiu  reagente-x 2014-05-24]
[termometro :temperatura 50° 2014-05-24]
[termometro :temperatura 60° 2014-05-25]
[motor :consumiu  reagente-y 2014-05-26]
[termometro :temperatura 65° 2014-05-26]
[termometro :temperatura 70° 2014-05-26]
[motor :consumiu  reagente-z 2014-05-27]
[termometro :temperatura 160° 2014-05-27]
[termometro :temperatura 200° 2014-05-28]

;; (as-of (db) 2014-05-26)

[motor :consumiu  reagente-x 2014-05-24]
[termometro :temperatura 50° 2014-05-24]
[termometro :temperatura 60° 2014-05-25]
[motor :consumiu  reagente-y 2014-05-26]
[termometro :temperatura 65° 2014-05-26]
[termometro :temperatura 70° 2014-05-26]

Testando migrações

;; let

(let [x 3]
  (+ x 4)) ;; => 7


;; db-let
(db-let [borked-user-1 {:name "joão"   :age "quarenta"}
         borked-user-2 {:name "nicole" :age "doze"}
         user-3 {:name "gould"  :age "74"}]
   (get-user borked-user-1) => (throws)
   (get-user borked-user-2) => (throws) 
   (get-user user-3)        => {:name "gould" :age "74"}
   (migration!!!)
   (get-user borked-user-1) => {:name "joão" :age 40}
   (get-user borked-user-2) => {:name "nicole" :age 12}
   (get-user user-3)        => {:name "gould" :age 74})

Programmabilidade

Schema

  • Systema de typos opcional
  • Como novo defn 
(defn bitcoin-price [market as-of]
   ...)

;; --------

(def valid-currencies (enum :USD :BRL :BTC :DOGE))
(def markets (enum :mercado-bitcoin :cryptsy))
(def exchange-rate 
  {:from valid-currencies 
   :to valid-currencies 
   :ratio Ratio})

(sm/defn bitcoin-price :- exchange-rate
  [market :- markets
   as-of  :- DateTime]
   ...)

(sm/defn bitcoin-price :- exchange-rate [market as-of]
   ...)

(sm/defn bitcoin-price
  [market :- markets
   as-of  :- DateTime]
   ...)

Flechas

;; Ex: digital currencies worth more than 1USD sorted by name

(sort-by :name (filter #(> (:worth-in-usd %) 1) (digital-currencies)))

(->>
  (digital-currencies)
  (filter #(> (:worth-in-usd %) 1)
  (sort-by :name))
(defmacro ->>
  "Threads the expr through the forms. Inserts x as the
  last item in the first form, making a list of it if it is not a
  list already. If there are more forms, inserts the first form as the
  last item in second form, etc."
  {:added "1.1"} 
  ([x form] (if (seq? form)
              (with-meta `(~(first form) ~@(next form)  ~x) (meta form))
              (list form x)))
  ([x form & more] `(->> (->> ~x ~form) ~@more)))
(->> 3 (/ 4))

(->> 3 str)

(->> 3 (/ 4) (* 5))

(->> (->> 3 (/ 4)) (* 5))

Utilitarios de teste

  • as-of
  • as-user
  • with-roles
(as-user "joãozinho"
  (GET "/userinfo") => ...

  (as-of (date 2014 5 24)
     (GET "/points") => ...)

  (as-of (date 2014 5 25)
     (GET "/points") => ...))

(with-roles ["user"]
   (POST "/destroy-everything") => ...)

Extendendo o BD

Addicionando attributos a um attributo

  • Attributo: idade
  • Como é definido?
{:db/id ...
 :db/ident :db/transform
 :db/valueType :db.type/keyword
 :db/cardinality :db.cardinality/one
 :db/doc "transformation for an entity"}
{:db/id ...
 :db/ident :person/age
 :db/valueType :db.type/long
 :db/cardinality :db.cardinality/one
 :db/doc "age for a person"}
{:db/id ...
 :db/ident :person/age
 :db/valueType :db.type/long
 :db/cardinality :db.cardinality/one
 :db/transform   :years
 :db/doc "age for a person"}

Proximos passos

clj-sp

  • www.meetup.com/clj-sp/
  • Video introductorio
  • Dojos quinzenaes

Desafio #5

  • Descryptographar string
  • Adivinhar tamanho correcto da chave
  • Menor entropia

Desafio #6

  • Chamar meia dúzia de funcções
  • Debuggar
  • Soffrer

Desafio de sempre

  • Mão na massa
  • Alto nivel
  • Divertir-se

:)

(clj ♥)

By Konrad Scorciapino

(clj ♥)

  • 883