Clojure workshop
   Alf Kristian Støyle
   Andreas Jacobsen
              
Agenda
•   Introduksjon - hvorfor er Clojure viktig

•   Basic syntax

    •   Oppgaver

    •   Gjennomgang av oppgaver

•   JSON over HTTP

    •   Oppgaver

    •   Gjennomgang

•   Oppsummering
Kontoeksempelet
public class Account {
  private long balance;
  public final int accountNo;

    public Account(long balance, int accountNo){
      this.balance = balance; this.accountNo = accountNo;
    }

    public void debit(long debitAmount) {
      this.balance -= debitAmount;
    }

    public void credit(long creditAmount) {
      this.balance += creditAmount;
    }

    public long getBalance() {
      return this.balance;
    }
}
public class Account {
  private long balance;
  public final int accountNo;

    public Account(long balance, int accountNo){
      this.balance = balance; this.accountNo = accountNo;
    }

    public synchronized void debit(long debitAmount) {
      this.balance -= debitAmount;
    }

    public synchronized void credit(long creditAmount) {
      this.balance += creditAmount;
    }

    public long getBalance() {
      return this.balance;
    }
}
public class Account {
  private long balance;
  public final int accountNo;

    public Account(long balance, int accountNo){
      this.balance = balance; this.accountNo = accountNo;
    }

    public synchronized void debit(long debitAmount) {
      this.balance -= debitAmount;
    }

    public synchronized void credit(long creditAmount) {
      this.balance += creditAmount;
    }

    public synchronized long getBalance() {
      return this.balance;
    }
}
public class Account {
  private volatile long balance;
  public final int accountNo;

    public Account(long balance, int accountNo){
      this.balance = balance; this.accountNo = accountNo;
    }

    public synchronized void debit(long debitAmount) {
      this.balance -= debitAmount;
    }

    public synchronized void credit(long creditAmount) {
      this.balance += creditAmount;
    }

    public synchronized long getBalance() {
      return this.balance;
    }
}
public void transfer(Account fromAccount, Account toAccount,
                     long amount) throws Exception {

     if (fromAccount.getBalance() < amount) {
          throw new Exception("Not enough money!");
     }
    fromAccount.debit(amount);
    toAccount.credit(amount);
}
public void transfer(Account fromAccount, Account toAccount,
                     long amount) throws Exception {

    synchronized (fromAccount) {
        synchronized (toAccount) {

           if (fromAccount.getBalance() < amount) {
                throw new Exception("Not enough money!");
  
         }
  
         fromAccount.debit(amount);

           toAccount.credit(amount);

       }
    }
}
public void transfer(Account fromAccount, Account toAccount,
                     long amount) throws Exception {

    Object mutex1 = toAccount;
    Object mutex2 = fromAccount;
    if (fromAccount.accountNo < toAccount.accountNo) {
        mutex1 = fromAccount;
        mutex2 = toAccount;
    }
    synchronized (mutex1) {
        synchronized (mutex2) {
            if (fromAccount.getBalance() < amount) {
                throw new Exception("Not enough money!");
            }
            fromAccount.debit(amount);
            toAccount.credit(amount);
        }
    }
}
public void transfer(Account fromAccount, Account toAccount,
                     long amount) throws Exception {

    Object mutex1 = toAccount;
    Object mutex2 = fromAccount;
    if (fromAccount.accountNo < toAccount.accountNo) {
        mutex1 = fromAccount;
        mutex2 = toAccount;




                                                                    ?
    }
    synchronized (mutex1) {
        synchronized (mutex2) {
            if (fromAccount.getBalance() < amount) {
                throw new Exception("Not enough money!");
            }
            fromAccount.debit(amount);
            toAccount.credit(amount);
        }
    }
}
        public class Account {
          private volatile long balance;
          public final int accountNo;

            public Account(long balance, int accountNo){
              this.balance = balance; this.accountNo = accountNo;
            }

            public synchronized void debit(long debitAmount) {
              this.balance -= debitAmount;
            }
        
            public synchronized void credit(long creditAmount) {
              this.balance += creditAmount;
            }

            public synchronized long getBalance() {
              return this.balance;
            }
        }
(defn transfer [from-account to-account amount]
 (dosync
  (if (> amount @from-account)
   (throw (new Exception "Not enough money!")))
  (alter from-account - amount)
  (alter to-account + amount)))
(defn transfer [from-account to-account amount]
 (dosync
  (if (> amount @from-account)
   (throw (new Exception "Not enough money!")))
  (alter from-account - amount)
  (alter to-account + amount)))

(def account-a (ref 1000))
(def account-b (ref 800))
(defn transfer [from-account to-account amount]
 (dosync
  (if (> amount @from-account)
   (throw (new Exception "Not enough money!")))
  (alter from-account - amount)
  (alter to-account + amount)))

(def account-a (ref 1000))
(def account-b (ref 800))


(transfer account-a account-b 300)

@account-a
; => 700
http://www.dehne.carleton.ca/research/multi-core
Concurrency
 dreier som om å gjøre flere oppgaver
 omtrent samtidig


Parallelism
 dreier seg om å dele en oppgave i mange
 deloppgaver som kan gjøres concurrent
Clojure
Accidental complexity
Clojure
• General purpose
• Lisp (List Processing)
• Funksjonelt
• Kompilert
• Dynamisk typet
• Tett knyttet til JVM’en
1
; => 1

"Hello World"
; => "Hello World"
1
; => 1

"Hello World"
; => "Hello World"


(class 1)
; => java.lang.Integer

(class "Hello world")
; => java.lang.String
(println "Hello " "world")
; “Hello world”
; => nil
Funksjonsnavn


(println "Hello " "world")
; “Hello world”
; => nil
Funksjonsnavn   Parametere


(println "Hello " "world")
; “Hello world”
; => nil
Funksjonsnavn   Parametere


(println "Hello " "world")
                 ,
; “Hello world”
; => nil
Prefiks notasjon
 Funksjonsnavn   Parametere


(println "Hello " "world")
                 ,
; “Hello world”
; => nil
Methods.callStatic();
methods.callInstance();

callStatic();
callInstance();

this.callInstance();
methods.callStatic();

Methods.this.callInstance();
Methods.this.callStatic();
(println "Hello world")
; Hello world
; => nil
(println "Hello world")
; Hello world
; => nil

(sum 1 2 3)
; => 6
(println "Hello world")
; Hello world
; => nil

(sum 1 2 3)
; => 6

(+ 1 2)
; => 3
(println "Hello world")
; Hello world
; => nil

(sum 1 2 3)
; => 6

(+ 1 2)
; => 3

(+ 1 2 3)
; => 6
(println "Hello world")
; Hello world
; => nil

(sum 1 2 3)
; => 6

(+ 1 2)
; => 3

(+ 1 2 3)
; => 6

(+)
; => 0
1 + 2 * 3
1 + 2 * 3

1 + (2 * 3)
1 + 2 * 3

1 + (2 * 3)

(+ 1 (* 2 3))
Funksjoner

(fn [& nums]
  (apply + nums))
Funksjoner
(def sum
  (fn [& nums]
    (apply + nums)))
Funksjoner
(def sum

              )
Funksjoner
(def sum
  (fn [& nums]
    (apply + nums)))
Funksjoner
(def sum
  (fn [& nums]
    (apply + nums)))


(defn sum
  [& nums] (apply + nums))
Lister!
'(3 2 1)
; => (3 2 1)

(+ 3 2 1)
; => 6
Lister!
'(3 2 1)
; => (3 2 1)

(+ 3 2 1)
; => 6


(defn iterate
  [f x] (cons x (lazy-seq (iterate f (f x)))))
Immutable collections
; List
'(3 2 1)

; Vector
[1 2 3]

; Set
#{1 2 3}

; Map
{1 "one", 2 "two"‚ 3 "three"}
Persistent data
        structures
(def my-list '(3 2 1))
; => (3 2 1)
Persistent data
        structures
(def my-list '(3 2 1))
; => (3 2 1)
Persistent data
        structures
(def my-list '(3 2 1))
; => (3 2 1)

(def my-other-list (cons 4 my-list))
; => (4 3 2 1)
Persistent data
        structures
(def my-list '(3 2 1))
; => (3 2 1)

(def my-other-list (cons 4 my-list))
; => (4 3 2 1)
Immutable records
(defrecord Person [fname lname])
; => user.Person


(Person. "Alf" "Støyle")
; => #:user.Person{:fname "Alf", :lname "Støyle"}
Immutable objects are always thread-safe.
Ren funksjonell
programmering


  f(x) = x + 1
Clojures filosofi
Verdier
 Immutable/uforanderlig, primitiv eller sammensatt
Clojures filosofi
Verdier
 Immutable/uforanderlig, primitiv eller sammensatt
Identitet
  En observert entitet som vi assosierer med en serie
  relaterte tilstander (verdier) over tid
Clojures filosofi
Verdier
 Immutable/uforanderlig, primitiv eller sammensatt
Identitet
  En observert entitet som vi assosierer med en serie
  relaterte tilstander (verdier) over tid
Tilstand
 Verdien til en identitet i på et gitt tidspunkt
Clojures filosofi
Verdier
 Immutable/uforanderlig, primitiv eller sammensatt
Identitet
  En observert entitet som vi assosierer med en serie
  relaterte tilstander (verdier) over tid
Tilstand
 Verdien til en identitet i på et gitt tidspunkt
Tid
 Relativ før/etter endring av identitet
Perception
Perception
Perception
Perception
Perception
Perception
Fra Rich Hickeys
“Are we there yet”
Reference types
• Atoms - synkron og ukoordinert oppdatering
• Agents - asynkron og ukoordinert oppdatering
• Refs - synkron og koordinert oppdatering
Reference types
• Atoms - synkron og ukoordinert oppdatering
• Agents - asynkron og ukoordinert oppdatering
• Refs - synkron og koordinert oppdatering
• Synkron perception
Atoms
(def an-atom (atom 0))
; => #'user/an-atom
Atoms
(def an-atom (atom 0))
; => #'user/an-atom

(swap! an-atom inc)
; => 1
Atoms
(def an-atom (atom 0))
; => #'user/an-atom

(swap! an-atom inc)
; => 1

(deref an-atom)
; => 1
Atoms
(def an-atom (atom 0))
; => #'user/an-atom

(swap! an-atom inc)
; => 1

(deref an-atom)
; => 1

@an-atom
; => 1
Agents
(def an-agent (agent 0))
; => #'user/an-atom
Agents
(def an-agent (agent 0))
; => #'user/an-atom

(send an-agent inc)
; => #<Agent@9b7c63f: 0>
Agents
(def an-agent (agent 0))
; => #'user/an-atom

(send an-agent inc)
; => #<Agent@9b7c63f: 0>

@an-agent
; => ; 0 eller 1 ??
Agents
(def an-agent (agent 0))
; => #'user/an-atom

(send an-agent inc)
; => #<Agent@9b7c63f: 0>

@an-agent              (await an-agent)
; => ; 0 eller 1 ??    ; => nil

                       @an-agent
                       ; => 1
Refs
(def ref-1 (ref 0))
; => #'user/ref-1

(def ref-2 (ref 0))
; => #'user/ref-2
Refs
(def ref-1 (ref 0))
; => #'user/ref-1

(def ref-2 (ref 0))
; => #'user/ref-2

(alter ref-1 inc)
Refs
(def ref-1 (ref 0))
; => #'user/ref-1

(def ref-2 (ref 0))
; => #'user/ref-2

(alter ref-1 inc)
; java.lang.IllegalStateException:
; No transaction running
Refs
(def ref-1 (ref 0))
; => #'user/ref-1

(def ref-2 (ref 0))
; => #'user/ref-2

(alter ref-1 inc)
; java.lang.IllegalStateException:
; No transaction running

(dosync (alter ref-1 inc))
; => 1
Refs
(dosync
  (alter ref-1 inc)
  (alter ref-2 dec))
; => -1
Refs
(dosync
  (alter ref-1 inc)
  (alter ref-2 dec))
; => -1


@ref-1
; => 2

@ref-2
; => -1
Refs
(dosync
  (alter ref-1 inc)
  (dosync
    (alter ref-2 dec)))
; => -2

@ref-1
; => 3

@ref-2
; => -2
Software transactional
      memory
Software transactional
      memory
Software transactional
      memory
   Transactional memory is to
  shared-memory concurrency
               as
     garbage collection is to
      memory management
Software transactional
      memory
Software transactional
      memory
    Atomic
    Consistent
    Isolated
    Durable
(defn transfer [from-account to-account amount]
 (dosync
  (if (> amount @from-account)
   (throw (new Exception "Not enough money!")))
  (alter from-account - amount)
  (alter to-account + amount)))

(def account-a (ref 1000))
(def account-b (ref 800))


(transfer account-a account-b 300)

@account-a
; => 700
Oppsummering
• Skiller tilstand og identitet
• Ingen mutable tilstand
• Ingenting blokkerer
• Clojure hjelper langt på vei med concurrency
Oppsummering
• Skiller tilstand og identitet
• Ingen mutable tilstand
• Ingenting blokkerer
• Clojure hjelper langt på vei med concurrency
• Mindre “accidental complexity”
Clojure syntaks
(Masse paranteser)
• REPL
• Syntaks
• Data strukturer
• Funksjoner
• Hvordan fylle ut oppgavene
• Hvordan finne hjelp
clojure-workshop/$ lein repl
Dette er en form
Dette er også en liste
Et uttrykk (expression)
Dette er en liste
Akkurat samme, skrevet litt lenger
Noen som klarer å gjette hva dette blir?
En funksjon er også bare data
Dette er en funksjon (uten navn)
Lost in Stupid Parentheses?
let lar deg binde lokale variable
Oppgaver!

     Disse ligger under
clojure-workshop/test/
clojure-workshop/test/
   (Dere ser ikke dobbelt)
Start med core.clj
c-w/$ lein test
c-w/$ lein test clojure-workshop.test.core
To streker: __ => En funksjon
Tre streker: ___ => En verdi
Alle testene er kommentert ut, flytt
          (comment
nedover for å kommentere inn tester
• http://clojuredocs.org
• http://clojure.org/cheatsheet
• Repl har innebygget hjelp
• (doc first)
• (find-doc “Returns       the first item”)

• (apropos ‘first)
• (source first)
JSON over HTTP
JSON
• JavaScript Object Notation
• http://www.json.org/
 • It is easy for humans to read and write.
 • It is easy for machines to parse and generate
{
     "firstName": "John",
     "lastName": "Smith",
     "age": 25,
     "address":
     {
         "streetAddress": "21 2nd Street",
         "city": "New York",
         "state": "NY",
         "postalCode": "10021"
     },
     "phoneNumber":
     [
           {
             "type": "home",
             "number": "212 555-1234"
         },
         {
             "type": "fax",
             "number": "646 555-4567"
         }
     ]
 }
         http://en.wikipedia.org/wiki/JSON
{
           "firstName": "John",
           "lastName": "Smith",
           "age": 25,
           "address":
           {
               "streetAddress": "21 2nd Street",
               "city": "New York",
               "state": "NY",
map        },
               "postalCode": "10021"

           "phoneNumber":
           [
                 {
                   "type": "home",
                   "number": "212 555-1234"
               },
               {
                   "type": "fax",
                   "number": "646 555-4567"
               }
           ]
       }
               http://en.wikipedia.org/wiki/JSON
{
              "firstName": "John",
              "lastName": "Smith",
              "age": 25,
              "address":
              {
                  "streetAddress": "21 2nd Street",
                  "city": "New York",
                  "state": "NY",
  map         },
                  "postalCode": "10021"

              "phoneNumber":
              [
                    {
                      "type": "home",
                      "number": "212 555-1234"
                  },
vector            {
                      "type": "fax",
                      "number": "646 555-4567"
                  }
              ]
          }
                  http://en.wikipedia.org/wiki/JSON
(clojure.data.json/read-json "...")
{
    :firstName John,
    :lastName Smith,
    :age 25,
    :address
    {
        :streetAddress 21 2nd Street,
        :city New York,
        :state NY,
        :postalCode 10021
    },
    :phoneNumber
    [
        {
          :type home,
          :number 212 555-1234
        }
        {
          :type fax,
          :number 646 555-4567
        }
    ]
}
{
     "firstName": "John",
     "lastName": "Smith",
     "age": 25,
     "address":
     {
         "streetAddress": "21 2nd Street",
         "city": "New York",
         "state": "NY",
         "postalCode": "10021"
     },
     "phoneNumber":
     [
           {
             "type": "home",
             "number": "212 555-1234"
         },
         {
             "type": "fax",
             "number": "646 555-4567"
         }
     ]
 }
(get {:one 1 :two 2 :three 3} :one)
;=> 1
(get {:one 1 :two 2 :three 3} :one)
;=> 1

(:one {:one 1 :two 2 :three 3})
;=> 1
(get {:one 1 :two 2 :three 3} :one)
;=> 1

(:one {:one 1 :two 2 :three 3})
;=> 1

({:one 1 :two 2 :three 3} :one)
;=> 1
clj-http

(client/get "http://google.com")
=> {:status 200
    :headers {"date" "Sun, 01 Aug 2010 07:03:49 GMT"
              "cache-control" "private, max-age=0"
              "content-type" "text/html; charset=ISO-8859-1"
              ...}
    :body "<!doctype html>..."}




           https://github.com/dakrone/clj-http
Oppgave
•   Eksempel på twitter json i “twitter-java-search-json.txt”

•   Skrive ut “tweet-text” fra live twitter søk

•   Skriv ut encodings benyttet i resultat av live twitter søk

•   twitter-java-search-json.txt

    •   Finn antall unike encodings

    •   Skriv ut tweets fra “world_finance”

    •   Skriv ut tweets som er replies

•   API’er

    •   https://github.com/dakrone/clj-http

    •   http://clojure.github.com/clojure-contrib/json-api.html
Lyst til å lære mer?
•   clojure.org

•   4clojure.com

•   github.com/functional-koans/clojure-koans
Takk for oss :)
•   Spørsmål:

    •   aks@knowit.no

    •   aja@knowit.no

•   Oppgaver: github.com/andreaja/clojure-workshop

•   Løsninger: github.com/andreaja/clojure-workshop/tree/solutions

Clojure workshop

  • 1.
    Clojure workshop Alf Kristian Støyle Andreas Jacobsen  
  • 2.
    Agenda • Introduksjon - hvorfor er Clojure viktig • Basic syntax • Oppgaver • Gjennomgang av oppgaver • JSON over HTTP • Oppgaver • Gjennomgang • Oppsummering
  • 3.
  • 4.
    public class Account{ private long balance; public final int accountNo; public Account(long balance, int accountNo){ this.balance = balance; this.accountNo = accountNo; } public void debit(long debitAmount) { this.balance -= debitAmount; } public void credit(long creditAmount) { this.balance += creditAmount; } public long getBalance() { return this.balance; } }
  • 5.
    public class Account{ private long balance; public final int accountNo; public Account(long balance, int accountNo){ this.balance = balance; this.accountNo = accountNo; } public synchronized void debit(long debitAmount) { this.balance -= debitAmount; } public synchronized void credit(long creditAmount) { this.balance += creditAmount; } public long getBalance() { return this.balance; } }
  • 6.
    public class Account{ private long balance; public final int accountNo; public Account(long balance, int accountNo){ this.balance = balance; this.accountNo = accountNo; } public synchronized void debit(long debitAmount) { this.balance -= debitAmount; } public synchronized void credit(long creditAmount) { this.balance += creditAmount; } public synchronized long getBalance() { return this.balance; } }
  • 7.
    public class Account{ private volatile long balance; public final int accountNo; public Account(long balance, int accountNo){ this.balance = balance; this.accountNo = accountNo; } public synchronized void debit(long debitAmount) { this.balance -= debitAmount; } public synchronized void credit(long creditAmount) { this.balance += creditAmount; } public synchronized long getBalance() { return this.balance; } }
  • 8.
    public void transfer(AccountfromAccount, Account toAccount, long amount) throws Exception { if (fromAccount.getBalance() < amount) { throw new Exception("Not enough money!"); } fromAccount.debit(amount); toAccount.credit(amount); }
  • 9.
    public void transfer(AccountfromAccount, Account toAccount, long amount) throws Exception { synchronized (fromAccount) { synchronized (toAccount) { if (fromAccount.getBalance() < amount) { throw new Exception("Not enough money!"); } fromAccount.debit(amount); toAccount.credit(amount); } } }
  • 10.
    public void transfer(AccountfromAccount, Account toAccount, long amount) throws Exception { Object mutex1 = toAccount; Object mutex2 = fromAccount; if (fromAccount.accountNo < toAccount.accountNo) { mutex1 = fromAccount; mutex2 = toAccount; } synchronized (mutex1) { synchronized (mutex2) { if (fromAccount.getBalance() < amount) { throw new Exception("Not enough money!"); } fromAccount.debit(amount); toAccount.credit(amount); } } }
  • 11.
    public void transfer(AccountfromAccount, Account toAccount, long amount) throws Exception { Object mutex1 = toAccount; Object mutex2 = fromAccount; if (fromAccount.accountNo < toAccount.accountNo) { mutex1 = fromAccount; mutex2 = toAccount; ? } synchronized (mutex1) { synchronized (mutex2) { if (fromAccount.getBalance() < amount) { throw new Exception("Not enough money!"); } fromAccount.debit(amount); toAccount.credit(amount); } } } public class Account { private volatile long balance; public final int accountNo; public Account(long balance, int accountNo){ this.balance = balance; this.accountNo = accountNo; } public synchronized void debit(long debitAmount) { this.balance -= debitAmount; } public synchronized void credit(long creditAmount) { this.balance += creditAmount; } public synchronized long getBalance() { return this.balance; } }
  • 12.
    (defn transfer [from-accountto-account amount] (dosync (if (> amount @from-account) (throw (new Exception "Not enough money!"))) (alter from-account - amount) (alter to-account + amount)))
  • 13.
    (defn transfer [from-accountto-account amount] (dosync (if (> amount @from-account) (throw (new Exception "Not enough money!"))) (alter from-account - amount) (alter to-account + amount))) (def account-a (ref 1000)) (def account-b (ref 800))
  • 14.
    (defn transfer [from-accountto-account amount] (dosync (if (> amount @from-account) (throw (new Exception "Not enough money!"))) (alter from-account - amount) (alter to-account + amount))) (def account-a (ref 1000)) (def account-b (ref 800)) (transfer account-a account-b 300) @account-a ; => 700
  • 15.
  • 16.
    Concurrency dreier somom å gjøre flere oppgaver omtrent samtidig Parallelism dreier seg om å dele en oppgave i mange deloppgaver som kan gjøres concurrent
  • 17.
  • 18.
  • 19.
    Clojure • General purpose •Lisp (List Processing) • Funksjonelt • Kompilert • Dynamisk typet • Tett knyttet til JVM’en
  • 20.
    1 ; => 1 "HelloWorld" ; => "Hello World"
  • 21.
    1 ; => 1 "HelloWorld" ; => "Hello World" (class 1) ; => java.lang.Integer (class "Hello world") ; => java.lang.String
  • 22.
    (println "Hello ""world") ; “Hello world” ; => nil
  • 23.
    Funksjonsnavn (println "Hello ""world") ; “Hello world” ; => nil
  • 24.
    Funksjonsnavn Parametere (println "Hello " "world") ; “Hello world” ; => nil
  • 25.
    Funksjonsnavn Parametere (println "Hello " "world") , ; “Hello world” ; => nil
  • 26.
    Prefiks notasjon Funksjonsnavn Parametere (println "Hello " "world") , ; “Hello world” ; => nil
  • 27.
  • 28.
    (println "Hello world") ;Hello world ; => nil
  • 29.
    (println "Hello world") ;Hello world ; => nil (sum 1 2 3) ; => 6
  • 30.
    (println "Hello world") ;Hello world ; => nil (sum 1 2 3) ; => 6 (+ 1 2) ; => 3
  • 31.
    (println "Hello world") ;Hello world ; => nil (sum 1 2 3) ; => 6 (+ 1 2) ; => 3 (+ 1 2 3) ; => 6
  • 32.
    (println "Hello world") ;Hello world ; => nil (sum 1 2 3) ; => 6 (+ 1 2) ; => 3 (+ 1 2 3) ; => 6 (+) ; => 0
  • 33.
    1 + 2* 3
  • 34.
    1 + 2* 3 1 + (2 * 3)
  • 35.
    1 + 2* 3 1 + (2 * 3) (+ 1 (* 2 3))
  • 36.
    Funksjoner (fn [& nums] (apply + nums))
  • 37.
    Funksjoner (def sum (fn [& nums] (apply + nums)))
  • 38.
  • 39.
    Funksjoner (def sum (fn [& nums] (apply + nums)))
  • 40.
    Funksjoner (def sum (fn [& nums] (apply + nums))) (defn sum [& nums] (apply + nums))
  • 41.
    Lister! '(3 2 1) ;=> (3 2 1) (+ 3 2 1) ; => 6
  • 42.
    Lister! '(3 2 1) ;=> (3 2 1) (+ 3 2 1) ; => 6 (defn iterate [f x] (cons x (lazy-seq (iterate f (f x)))))
  • 43.
    Immutable collections ; List '(32 1) ; Vector [1 2 3] ; Set #{1 2 3} ; Map {1 "one", 2 "two"‚ 3 "three"}
  • 44.
    Persistent data structures (def my-list '(3 2 1)) ; => (3 2 1)
  • 45.
    Persistent data structures (def my-list '(3 2 1)) ; => (3 2 1)
  • 46.
    Persistent data structures (def my-list '(3 2 1)) ; => (3 2 1) (def my-other-list (cons 4 my-list)) ; => (4 3 2 1)
  • 47.
    Persistent data structures (def my-list '(3 2 1)) ; => (3 2 1) (def my-other-list (cons 4 my-list)) ; => (4 3 2 1)
  • 48.
    Immutable records (defrecord Person[fname lname]) ; => user.Person (Person. "Alf" "Støyle") ; => #:user.Person{:fname "Alf", :lname "Støyle"}
  • 49.
    Immutable objects arealways thread-safe.
  • 50.
  • 51.
  • 52.
    Clojures filosofi Verdier Immutable/uforanderlig,primitiv eller sammensatt Identitet En observert entitet som vi assosierer med en serie relaterte tilstander (verdier) over tid
  • 53.
    Clojures filosofi Verdier Immutable/uforanderlig,primitiv eller sammensatt Identitet En observert entitet som vi assosierer med en serie relaterte tilstander (verdier) over tid Tilstand Verdien til en identitet i på et gitt tidspunkt
  • 54.
    Clojures filosofi Verdier Immutable/uforanderlig,primitiv eller sammensatt Identitet En observert entitet som vi assosierer med en serie relaterte tilstander (verdier) over tid Tilstand Verdien til en identitet i på et gitt tidspunkt Tid Relativ før/etter endring av identitet
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
    Fra Rich Hickeys “Arewe there yet”
  • 62.
    Reference types • Atoms- synkron og ukoordinert oppdatering • Agents - asynkron og ukoordinert oppdatering • Refs - synkron og koordinert oppdatering
  • 63.
    Reference types • Atoms- synkron og ukoordinert oppdatering • Agents - asynkron og ukoordinert oppdatering • Refs - synkron og koordinert oppdatering • Synkron perception
  • 64.
    Atoms (def an-atom (atom0)) ; => #'user/an-atom
  • 65.
    Atoms (def an-atom (atom0)) ; => #'user/an-atom (swap! an-atom inc) ; => 1
  • 66.
    Atoms (def an-atom (atom0)) ; => #'user/an-atom (swap! an-atom inc) ; => 1 (deref an-atom) ; => 1
  • 67.
    Atoms (def an-atom (atom0)) ; => #'user/an-atom (swap! an-atom inc) ; => 1 (deref an-atom) ; => 1 @an-atom ; => 1
  • 68.
    Agents (def an-agent (agent0)) ; => #'user/an-atom
  • 69.
    Agents (def an-agent (agent0)) ; => #'user/an-atom (send an-agent inc) ; => #<Agent@9b7c63f: 0>
  • 70.
    Agents (def an-agent (agent0)) ; => #'user/an-atom (send an-agent inc) ; => #<Agent@9b7c63f: 0> @an-agent ; => ; 0 eller 1 ??
  • 71.
    Agents (def an-agent (agent0)) ; => #'user/an-atom (send an-agent inc) ; => #<Agent@9b7c63f: 0> @an-agent (await an-agent) ; => ; 0 eller 1 ?? ; => nil @an-agent ; => 1
  • 72.
    Refs (def ref-1 (ref0)) ; => #'user/ref-1 (def ref-2 (ref 0)) ; => #'user/ref-2
  • 73.
    Refs (def ref-1 (ref0)) ; => #'user/ref-1 (def ref-2 (ref 0)) ; => #'user/ref-2 (alter ref-1 inc)
  • 74.
    Refs (def ref-1 (ref0)) ; => #'user/ref-1 (def ref-2 (ref 0)) ; => #'user/ref-2 (alter ref-1 inc) ; java.lang.IllegalStateException: ; No transaction running
  • 75.
    Refs (def ref-1 (ref0)) ; => #'user/ref-1 (def ref-2 (ref 0)) ; => #'user/ref-2 (alter ref-1 inc) ; java.lang.IllegalStateException: ; No transaction running (dosync (alter ref-1 inc)) ; => 1
  • 76.
    Refs (dosync (alterref-1 inc) (alter ref-2 dec)) ; => -1
  • 77.
    Refs (dosync (alterref-1 inc) (alter ref-2 dec)) ; => -1 @ref-1 ; => 2 @ref-2 ; => -1
  • 78.
    Refs (dosync (alterref-1 inc) (dosync (alter ref-2 dec))) ; => -2 @ref-1 ; => 3 @ref-2 ; => -2
  • 79.
  • 80.
  • 81.
    Software transactional memory Transactional memory is to shared-memory concurrency as garbage collection is to memory management
  • 82.
  • 83.
    Software transactional memory Atomic Consistent Isolated Durable
  • 85.
    (defn transfer [from-accountto-account amount] (dosync (if (> amount @from-account) (throw (new Exception "Not enough money!"))) (alter from-account - amount) (alter to-account + amount))) (def account-a (ref 1000)) (def account-b (ref 800)) (transfer account-a account-b 300) @account-a ; => 700
  • 86.
    Oppsummering • Skiller tilstandog identitet • Ingen mutable tilstand • Ingenting blokkerer • Clojure hjelper langt på vei med concurrency
  • 87.
    Oppsummering • Skiller tilstandog identitet • Ingen mutable tilstand • Ingenting blokkerer • Clojure hjelper langt på vei med concurrency • Mindre “accidental complexity”
  • 88.
  • 89.
    • REPL • Syntaks •Data strukturer • Funksjoner • Hvordan fylle ut oppgavene • Hvordan finne hjelp
  • 91.
  • 92.
  • 93.
  • 94.
  • 97.
  • 98.
  • 99.
    Noen som klarerå gjette hva dette blir?
  • 100.
    En funksjon erogså bare data
  • 101.
    Dette er enfunksjon (uten navn)
  • 102.
    Lost in StupidParentheses?
  • 103.
    let lar degbinde lokale variable
  • 104.
    Oppgaver! Disse ligger under clojure-workshop/test/ clojure-workshop/test/ (Dere ser ikke dobbelt)
  • 105.
  • 106.
    c-w/$ lein test c-w/$lein test clojure-workshop.test.core
  • 107.
    To streker: __=> En funksjon Tre streker: ___ => En verdi
  • 110.
    Alle testene erkommentert ut, flytt (comment nedover for å kommentere inn tester
  • 111.
    • http://clojuredocs.org • http://clojure.org/cheatsheet •Repl har innebygget hjelp • (doc first) • (find-doc “Returns the first item”) • (apropos ‘first) • (source first)
  • 112.
  • 113.
    JSON • JavaScript ObjectNotation • http://www.json.org/ • It is easy for humans to read and write. • It is easy for machines to parse and generate
  • 114.
    { "firstName": "John", "lastName": "Smith", "age": 25, "address": { "streetAddress": "21 2nd Street", "city": "New York", "state": "NY", "postalCode": "10021" }, "phoneNumber": [ { "type": "home", "number": "212 555-1234" }, { "type": "fax", "number": "646 555-4567" } ] } http://en.wikipedia.org/wiki/JSON
  • 115.
    { "firstName": "John", "lastName": "Smith", "age": 25, "address": { "streetAddress": "21 2nd Street", "city": "New York", "state": "NY", map }, "postalCode": "10021" "phoneNumber": [ { "type": "home", "number": "212 555-1234" }, { "type": "fax", "number": "646 555-4567" } ] } http://en.wikipedia.org/wiki/JSON
  • 116.
    { "firstName": "John", "lastName": "Smith", "age": 25, "address": { "streetAddress": "21 2nd Street", "city": "New York", "state": "NY", map }, "postalCode": "10021" "phoneNumber": [ { "type": "home", "number": "212 555-1234" }, vector { "type": "fax", "number": "646 555-4567" } ] } http://en.wikipedia.org/wiki/JSON
  • 117.
  • 118.
    { :firstName John, :lastName Smith, :age 25, :address { :streetAddress 21 2nd Street, :city New York, :state NY, :postalCode 10021 }, :phoneNumber [ { :type home, :number 212 555-1234 } { :type fax, :number 646 555-4567 } ] }
  • 119.
    { "firstName": "John", "lastName": "Smith", "age": 25, "address": { "streetAddress": "21 2nd Street", "city": "New York", "state": "NY", "postalCode": "10021" }, "phoneNumber": [ { "type": "home", "number": "212 555-1234" }, { "type": "fax", "number": "646 555-4567" } ] }
  • 120.
    (get {:one 1:two 2 :three 3} :one) ;=> 1
  • 121.
    (get {:one 1:two 2 :three 3} :one) ;=> 1 (:one {:one 1 :two 2 :three 3}) ;=> 1
  • 122.
    (get {:one 1:two 2 :three 3} :one) ;=> 1 (:one {:one 1 :two 2 :three 3}) ;=> 1 ({:one 1 :two 2 :three 3} :one) ;=> 1
  • 123.
    clj-http (client/get "http://google.com") => {:status200 :headers {"date" "Sun, 01 Aug 2010 07:03:49 GMT" "cache-control" "private, max-age=0" "content-type" "text/html; charset=ISO-8859-1" ...} :body "<!doctype html>..."} https://github.com/dakrone/clj-http
  • 124.
    Oppgave • Eksempel på twitter json i “twitter-java-search-json.txt” • Skrive ut “tweet-text” fra live twitter søk • Skriv ut encodings benyttet i resultat av live twitter søk • twitter-java-search-json.txt • Finn antall unike encodings • Skriv ut tweets fra “world_finance” • Skriv ut tweets som er replies • API’er • https://github.com/dakrone/clj-http • http://clojure.github.com/clojure-contrib/json-api.html
  • 125.
    Lyst til ålære mer? • clojure.org • 4clojure.com • github.com/functional-koans/clojure-koans
  • 126.
    Takk for oss:) • Spørsmål: • aks@knowit.no • aja@knowit.no • Oppgaver: github.com/andreaja/clojure-workshop • Løsninger: github.com/andreaja/clojure-workshop/tree/solutions

Editor's Notes

  • #2 \n
  • #3 \n
  • #4 Hvem kan FP?\nHvem kan Lisp?\nHvem kan Java?\n
  • #5 accountNo -&gt; final. Det er helt uproblematisk at dette er et public felt, i hvert fall fra et concurrency perspektiv.\n\n+= og -= er syntaktisk sukker for 3 operasjoner, read-write-store.\n
  • #6 += og -= er syntaktisk sukker for 3 operasjoner, read-write-store.\n
  • #7 += og -= er syntaktisk sukker for 3 operasjoner, read-write-store.\n
  • #8 += og -= er syntaktisk sukker for 3 operasjoner, read-write-store.\n
  • #9 \n
  • #10 Forhindre samtidig oppdatering ved &amp;#xE5; l&amp;#xE5;se p&amp;#xE5; objektene.\n\nDette ser vel og bra ut, men med litt uheldig timing vil \n
  • #11 Innf&amp;#xF8;re deterministisk l&amp;#xE5;serekkef&amp;#xF8;lge\n
  • #12 Har vi klart &amp;#xE5; unng&amp;#xE5; alle mulige feil fra denne koden?\n* Slik kode er sv&amp;#xE6;rt vanskelig &amp;#xE5; resonnere rundt, og selv eksperter har problemer. Jeg kan helt &amp;#xE6;rlig si at jeg ikke vet om denne koden er korrekt.\n* Et felt som kan endre seg -&gt; Gir seg selv at i en ekte applikasjon vil sitausjonen v&amp;#xE6;re mye v&amp;#xE6;rre.\n* Det som v&amp;#xE6;rre er, er at slik kode er nesten umulig &amp;#xE5; teste. Feilsituasjoner med tr&amp;#xE5;der oppst&amp;#xE5;r kun som f&amp;#xF8;lge av uheldig timing.\n* Hva er s&amp;#xE5; problemet her, hvorfor er dette s&amp;#xE5; vanskelig. Jo, vi programmerer med eksplisitte l&amp;#xE5;ser, noe som i praksis viser seg &amp;#xE5; v&amp;#xE6;re en sv&amp;#xE6;rt d&amp;#xE5;rlig abstraksjon.\n\nDet m&amp;#xE5; finnes bedre alternativer\n
  • #13 \n
  • #14 \n
  • #15 \n
  • #16 Korrekthet og ytelse\nPresisere at det vi skal snakke om er Concurrency.\n
  • #17 Startet mars i 2006.\nF&amp;#xF8;rste versjon 4 May 2009\nFikk veldig mye oppmerksomhet.\n
  • #18 Alle problemer har en inherent complexity. Dette er det som uansett m&amp;#xE5; til for &amp;#xE5; l&amp;#xF8;se problemet.\n
  • #19 F&amp;#xF8;rst lisp i 1958 John McCarthy\nIkke objektorientert\nYtelse nesten som Java\n
  • #20 \n
  • #21 Cambridge polish notation\n
  • #22 Cambridge polish notation\n
  • #23 Cambridge polish notation\n
  • #24 Cambridge polish notation\n
  • #25 Cambridge polish notation\n
  • #26 Cambridge polish notation\n
  • #27 Cambridge polish notation\n
  • #28 \n
  • #29 \n
  • #30 \n
  • #31 \n
  • #32 \n
  • #33 \n
  • #34 \n
  • #35 \n
  • #36 \n
  • #37 \n
  • #38 \n
  • #39 \n
  • #40 \n
  • #41 \n
  • #42 \n
  • #43 \n
  • #44 \n
  • #45 \n
  • #46 \n
  • #47 \n
  • #48 \n
  • #49 \n
  • #50  Med l&amp;#xE5;semodell, vil programmet g&amp;#xE5; tregere jo flere som oppfatter/perceives meg?\n
  • #51 \n
  • #52 \n
  • #53 \n
  • #54 Epokisk tidsmodell\n
  • #55 \n
  • #56 Gjenta egenskaper! N&amp;#xE5;r brukes dette!\n
  • #57 Gjenta egenskaper! N&amp;#xE5;r brukes dette!\n
  • #58 Gjenta egenskaper! N&amp;#xE5;r brukes dette!\n
  • #59 Gjenta egenskaper. N&amp;#xE5;r brukes dette!\nActors vs agents:\nAc -&gt; Sende tilstand til oppf&amp;#xF8;rsel\nAg -&gt; Sende oppf&amp;#xF8;rsel til tilstand\nSynkron perception\n
  • #60 Gjenta egenskaper. N&amp;#xE5;r brukes dette!\nActors vs agents:\nAc -&gt; Sende tilstand til oppf&amp;#xF8;rsel\nAg -&gt; Sende oppf&amp;#xF8;rsel til tilstand\nSynkron perception\n
  • #61 Gjenta egenskaper. N&amp;#xE5;r brukes dette!\nActors vs agents:\nAc -&gt; Sende tilstand til oppf&amp;#xF8;rsel\nAg -&gt; Sende oppf&amp;#xF8;rsel til tilstand\nSynkron perception\n
  • #62 Gjenta egenskaper, n&amp;#xE5;r brukes dette\n
  • #63 Gjenta egenskaper, n&amp;#xE5;r brukes dette\n
  • #64 Gjenta egenskaper, n&amp;#xE5;r brukes dette\n
  • #65 \n
  • #66 \n
  • #67 STM var en av hoved&amp;#xE5;rsakene til at Clojure ble s&amp;#xE5;pass fort kjent.\nAnalogi\n
  • #68 Snakke om .Net prosjektet\n
  • #69 Atomic - rollback ved transactions ellers vil det committe\nConsistent - constraints i database, set-validator\nIsolated - Snapshot MVCC\nMen... kan gi rollback.\nEget eksempel 10 000 retries.\nEksempel tungt oppdaterer en ref som f&amp;#xE5; konkurrerer om. S&amp;#xE5; gj&amp;#xF8;r den en lett jobb som oppdaterer en ref som mange konkurrerer om.\n
  • #70 Atomic - rollback ved transactions ellers vil det committe\nConsistent - constraints i database, set-validator\nIsolated - Snapshot MVCC\nMen... kan gi rollback.\nEget eksempel 10 000 retries.\nEksempel tungt oppdaterer en ref som f&amp;#xE5; konkurrerer om. S&amp;#xE5; gj&amp;#xF8;r den en lett jobb som oppdaterer en ref som mange konkurrerer om.\n
  • #71 Atomic - rollback ved transactions ellers vil det committe\nConsistent - constraints i database, set-validator\nIsolated - Snapshot MVCC\nMen... kan gi rollback.\nEget eksempel 10 000 retries.\nEksempel tungt oppdaterer en ref som f&amp;#xE5; konkurrerer om. S&amp;#xE5; gj&amp;#xF8;r den en lett jobb som oppdaterer en ref som mange konkurrerer om.\n
  • #72 \n
  • #73 N&amp;#xE5;r man tenker seg om -&gt; fornuftig m&amp;#xE5;te &amp;#xE5; modellere tilstand p&amp;#xE5;. Bonusen er jo da at dette fungerer veldig bra i en concurrent setting.\n
  • #74 N&amp;#xE5;r man tenker seg om -&gt; fornuftig m&amp;#xE5;te &amp;#xE5; modellere tilstand p&amp;#xE5;. Bonusen er jo da at dette fungerer veldig bra i en concurrent setting.\n
  • #75 \n
  • #76 \n
  • #77 Repl, dere kan f&amp;#xF8;lge med p&amp;#xE5; eksemplene. Read. Eval. Print. Loop.\n
  • #78 +Enten clj, eller IDE, eller+ lein repl\n
  • #79 Grunnenheten i spr&amp;#xE5;ket. Angir et uttrykk. \n
  • #80 Reader? \n
  • #81 Parantesene betyr at dette er uttryk som returnerer noe. \n
  • #82 F&amp;#xF8;rste symbolet blir kallt som en funksjon\n
  • #83 Dette er parametere\n
  • #84 Merket foran betyr at det skal leses som en liste og ikke eksekveres\n
  • #85 \n
  • #86 \n
  • #87 Funksjon som parameter. \n
  • #88 fn lager en funksjon,\narg er et argument, kunne brukt hva som helst som navn\narg + 5 = resultat\n
  • #89 Mange paranteser. F&amp;#xF8;rste parantes betyr: n&amp;#xE5; skal vi kalle noe. Skal kalle det som kommer fra andre parantes. Det er en funksjon. \n
  • #90 Symbolet &amp;#x201C;five&amp;#x201D; har en verdi, men kun innenfor parentesene til let\n
  • #91 \n
  • #92 Organisert med tester, hver test har en eller flere ting som skal fylles inn. Trenger bare endre p&amp;#xE5;&amp;#xA0;ting innenfor en &amp;#x201C;deftest&amp;#x201D;.\n
  • #93 F&amp;#xF8;rste kj&amp;#xF8;rer alle testene (oppgavene), andre kj&amp;#xF8;rer bare de f&amp;#xF8;rste oppgavene. Disse skal resultere i masse feilmeldinger.\n
  • #94 \n
  • #95 \n
  • #96 Eksempel p&amp;#xE5;&amp;#xA0;test, tester likhet mellom 1 og 1, true og true. \n
  • #97 \n
  • #98 \n
  • #99 \n
  • #100 \n
  • #101 \n
  • #102 \n
  • #103 \n
  • #104 \n
  • #105 \n
  • #106 \n
  • #107 \n
  • #108 \n
  • #109 \n
  • #110 \n
  • #111 \n
  • #112 \n
  • #113 \n