infoshare 2011 - jacek laskowski - programowanie funkcjonalne funkcyjnie z clojure praktycznie

42
Programowanie funkcjonalne funkcyjnie z Clojure praktycznie O budowaniu współbieżnej aplikacji graficznej Jacek Laskowski http://www.JacekLaskowski.pl wersja 1.0, 12.05.2011 [email protected]

Upload: infoshare

Post on 17-Jan-2015

1.256 views

Category:

Documents


1 download

DESCRIPTION

 

TRANSCRIPT

Page 1: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

Programowanie funkcjonalne funkcyjnie z Clojure praktycznie

O budowaniu współbieżnej aplikacji graficznej

Jacek Laskowski

http://www.JacekLaskowski.plwersja 1.0, 12.05.2011

[email protected]

Page 2: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

Ja...cek Laskowski• Entuzjasta Java EE, OSGi, SCA oraz programowania funkcyjnego (Clojure)

• Założyciel i lider Warszawa JUG

• Organizator Confitura 2011

• Członek zespołu NetBeans DreamTeam

• Blogger na http://JacekLaskowski.pl

• Blogger na http://blog.japila.pl

• Twittuje jako @jaceklaskowski

• Członek zespołów Apache Geronimo i Apache OpenEJB

• Specjalista produktów IBM WebSphere w IBM Polska

Page 3: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

konferencja społeczności javowej w Polsce

Confitura 2011http://confitura.pl

11 czerwiecWarszawa

(poprzednio Javarsovia)

Page 4: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie
Page 5: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

• Programming Concurrency on the JVM: Mastering Synchronization, STM, and Actorshttp://www.jaceklaskowski.pl/wiki/Book_review:_Programming_Concurrency_on_the_JVM

• Java Concurrency in Practicehttp://jcip.net

Źródła inspiracji

Page 6: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

$ java -versionjava version "1.6.0_24"Java(TM) SE Runtime Environment (build 1.6.0_24-b07-334-10M3326)Java HotSpot(TM) 64-Bit Server VM (build 19.1-b02-334, mixed mode)

$ cljuser=> (clojure-version)"1.3.0-alpha6"

Page 7: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

user=> ; przestrzeń nazewnicza (ang. namespace) w Clojureuser=> ; mapa symboli na ich odpowiedniki pełne - odnośniki i klasyuser=> (ns gui)nilgui=> gui=> (def nazwa-konferencji "InfoShare")#'gui/nazwa-konferencjigui=> (import javax.swing.JFrame)javax.swing.JFramegui=> (use 'clojure.contrib.swing-utils)nilgui=> (ns-interns 'gui){nazwa-konferencji #'gui/nazwa-konferencji}

Page 8: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

gui=> (import (javax.swing JFrame JButton JTextField JOptionPane))javax.swing.JOptionPanegui=> (import (java.awt GridLayout))java.awt.GridLayoutgui=> (use '[clojure.contrib.swing-utils :only (add-action-listener)])nil

Page 9: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

gui=> (JFrame. nazwa-konferencji)#<JFrame javax.swing.JFrame[frame1,0,22,0x0,invalid,hidden,layout=java.awt.BorderLayout,title=InfoShare,resizable,normal,defaultCloseOperation=HIDE_ON_CLOSE,rootPane=javax.swing.JRootPane[,0,0,0x0,invalid,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777673,maximumSize=,minimumSize=,preferredSize=],rootPaneCheckingEnabled=true]>

Page 10: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

gui=> (def f (JFrame. nazwa-konferencji))#'gui/fgui=> (doto f .pack .show)#<JFrame javax.swing.JFrame[frame2,0,22,128x37,layout=java.awt.BorderLayout,title=InfoShare,resizable,normal,defaultCloseOperation=HIDE_ON_CLOSE,rootPane=javax.swing.JRootPane[,0,22,128x15,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777673,maximumSize=,minimumSize=,preferredSize=],rootPaneCheckingEnabled=true]>

Page 11: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie
Page 12: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

gui=> (.setSize f 600 300)nil

Page 13: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie
Page 14: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

gui=> (def word-input-field (JTextField. 30))#'gui/word-input-fieldgui=> (defn create-enter-handler [input-field] (fn enter-handler [event] (let [w (.. input-field getText) msg (format "<html>Input: <b>%s</b></html>" w)] (do (JOptionPane/showMessageDialog nil msg "Information" JOptionPane/INFORMATION_MESSAGE) (.. input-field (requestFocusInWindow)) (.. input-field (selectAll))))))#'gui/create-enter-handler

Page 15: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

gui=> (add-action-listener word-input-field (create-enter-handler word-input-field))#<Object$ActionListener$46793e3a clojure.contrib.swing_utils.proxy$java.lang.Object$ActionListener$46793e3a@50152643>gui=> (.add f word-input-field)#<JTextField javax.swing.JTextField[...]>gui=> (.pack f)nil

Page 16: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie
Page 17: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie
Page 18: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

Programming Concurrency on the JVM, page 18

Page 19: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

Programming Concurrency on the JVM, page 22

Page 20: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

Model pamięci JavaMemory barrier

Page 21: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

• Clojure jest językiem funkcyjnym

• Clojure hołduje funkcjom czystym (ang. pure functions)

• Tożsamość (ang. identity) = logiczny byt, symbol

• Stan (ang. state) = wartość

• Czas (ang. time) = migawka

• Clojure oddziela tożsamość od stanu = upraszcza współbieżność

Page 22: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

Współbieżnośćvs

wielowątkowość

Page 23: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

http://twitpic.com/4wdy02

Page 24: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

Sztandarowy program współbieżny w Clojure

ants.cljhttp://paste.lisp.org/display/81878/raw

Page 25: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

$ wc ants.clj 319 1323 9727 ants.clj

$ grep Thread ants.clj (. Thread (sleep ant-sleep-ms)) (. Thread (sleep animation-sleep-ms)) (. Thread (sleep evap-sleep-ms))

Page 26: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

$ cljClojure 1.3.0-alpha6user=> (load-file "ants.clj")nil

Page 27: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

user=> (def ants (setup))#'user/antsuser=> (send-off animator animation)#<Agent@12dfbabd: nil>

Page 28: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

user=> (dorun (map #(send-off % behave) ants))nil

Page 29: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

Clojure a stan

• 4 rodzaje referencji (odwołań do pamięci) w Clojure

• Vars - dynamiczna referencja do zmiennej wartości (per wątek)

• Refs - transakcyjny Var dla wielu wątków

• Agents - asynchroniczny i niezależny

• Atoms - synchroniczny i niezależny stan

Page 30: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

STAN

Page 31: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

STAN

Page 32: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

$ grep agent ants.clj "create an ant at the location, returning an ant agent on the location" (agent loc)))) "places initial food and ants, returns seq of ant agents";ant agent functions;an ant agent tracks the location of an ant, and controls the behavior of "the main function for the ant agent" (send-off *agent* #'behave))(def animator (agent nil)) (send-off *agent* #'animation))(def evaporator (agent nil)) (send-off *agent* #'evaporation))

Page 33: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

$ grep ref ants.clj;world is a 2d vector of refs to cells (apply vector (map (fn [_] (ref (struct cell 0 0))) (rank-by (comp #(if (:home %) 1 0) deref) places) (rank-by (comp :pher deref) places))] (rank-by (comp :food deref) places) (rank-by (comp :pher deref) places))] (.setPreferredSize (new Dimension

Page 34: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

$ grep atom ants.clj

Page 35: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

user=> (doc future)-------------------------clojure.core/future([& body])Macro Takes a body of expressions and yields a future object that will invoke the body in another thread, and will cache the result and return it on all subsequent calls to deref/@. If the computation has not yet finished, calls to deref/@ will block.

Page 36: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

user=> (source future-cancel)(defn future-cancel "Cancels the future, if possible." {:added "1.1" :static true} [^java.util.concurrent.Future f] (.cancel f true))

Page 37: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

user=> (doc pmap)-------------------------clojure.core/pmap([f coll] [f coll & colls]) Like map, except f is applied in parallel. Semi-lazy in that the parallel computation stays ahead of the consumption, but doesn't realize the entire result unless required. Only useful for computationally intensive functions where the time of f dominates the coordination overhead.user=> (doc pcalls)-------------------------clojure.core/pcalls([& fns]) Executes the no-arg fns in parallel, returning a lazy sequence of their values

Page 38: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

clojure.lang.Agentuser=> (source agent)(defn agent... ([state & options] (let [a (new clojure.lang.Agent state) opts (apply hash-map options)] (setup-reference a options) (when (:error-handler opts) (.setErrorHandler a (:error-handler opts))) (.setErrorMode a (or (:error-mode opts) (if (:error-handler opts) :continue :fail))) a)))

Page 39: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

$ javap -classpath clojure.jar clojure.lang.AgentCompiled from "Agent.java"public class clojure.lang.Agent extends clojure.lang.ARef{ java.util.concurrent.atomic.AtomicReference aq; public static final java.util.concurrent.ExecutorService pooledExecutor; public static final java.util.concurrent.ExecutorService soloExecutor; public java.lang.Object dispatch(clojure.lang.IFn, clojure.lang.ISeq, boolean); static void dispatchAction(clojure.lang.Agent$Action); void enqueue(clojure.lang.Agent$Action); public int getQueueCount(); public static int releasePendingSends(); ...

Page 40: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

clojure.lang.Atomuser=> (source atom)(defn atom... ([x] (new clojure.lang.Atom x)) ([x & options] (setup-reference (atom x) options)))

Page 41: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

clojure.lang.Refuser=> (source ref)(defn ref... ([x] (new clojure.lang.Ref x)) ([x & options] (let [r ^clojure.lang.Ref (setup-reference (ref x) options) opts (apply hash-map options)] (when (:max-history opts) (.setMaxHistory r (:max-history opts))) (when (:min-history opts) (.setMinHistory r (:min-history opts))) r)))

Page 42: infoShare 2011 - Jacek Laskowski - Programowanie Funkcjonalne Funkcyjnie z Clojure Praktycznie

Programowanie funkcjonalne funkcyjnie z Clojure praktycznie

O budowaniu współbieżnej aplikacji graficznej

Jacek Laskowski

http://www.JacekLaskowski.plwersja 1.0, 12.05.2011

[email protected]