INTEROPERABILITY  CLOJURE      PYTHON      Enrico Franchi
2           OUTLINE   Why Clojure? Why Java?    Clojure from 3000 m.Jython-Clojure interoperabilityClojure-Jython interope...
3                         GENERAL NOTESDuring this presentation some very explicit Java code may be shown.  No ducks were ...
4               JVM LANGUAGESJython               Java                        ?                     JVM         ENRICO FRA...
5               JVM LANGUAGESJython               Java                        Clojure                     JVM         ENRI...
6                           CLOJURE                       Clojure is Lisp                    Clojure is a good Lisp   Cloj...
7                    JVM LANGUAGES                        Jython            Implementation of Python in Java              ...
8                   CLOJURE               ~ Good Parts ~         Functional Programming                  Laziness         ...
9       ATOMIC TYPES           Integers  Floating Point NumbersRatios (3/4 is not 0.75, is ¾)         BigDecimal       Str...
10                                    SEQUENCE TYPES                                 Python                   Common Lisp ...
11                        CLOJURE EXAMPLE(defn rember [a lat]  (cond   (empty? lat) ()   (= (first lat) a) (rest lat)   :e...
12                           TAIL CALL OPTIMIZATION(defn multirember [a lat]  (letfn      [(multirember-aux [source sink] ...
13                                      LAZINESS(defn lazy-multirember [a lat]  (letfn      [(multirember-aux [source]    ...
14                       NAMESPACES & MODULES(ns example.namespace)                    (ns example.namespace              ...
15                                   CALLING JAVAJava                         Clojure                               Jython...
16                                                    PROXIES(ns gui-sample  (:import [javax.swing JFrame JButton]        ...
17                                          PROXIES(ns gui-sample  (:import [javax.swing JFrame JButton]           [java.a...
18                                GEN-CLASS(ns example.ClassExample  (:gen-class   :name example.ClassExample   :extends O...
19                              GEN-CLASS (2)(defn show [coll]               (defn -show [coll]  (if (seq coll)           ...
20                         IMPLEMENTING PYOBJECTS                               IN CLOJURE                                ...
21                        IMPLEMENTING PYOBJECTS                             IN CLOJURE (2)(defmacro delegate-to-state [sy...
22                        IMPLEMENTING PYOBJECTS                                                                 print my_...
23                                  CLOJURE RT                             from clojure.lang import RT, Compilersource = (...
24                                 CLOJURE DECORATORimport pyclj@pyclj.clojuredef rember(a, lat):    ’’’(defn rember      ...
25                              IMPLEMENTATIONdef clojure(fn):    """Decorator that substitutes an empty python function w...
26                     IMPLEMENTATION (2)def determine_clojure_namespace(fn):    try:        clj_namespace = fn.__module__...
27                        IMPLEMENTATION (3)def build_clojure_function_object(clj_namespace, fn):    clojure_code = (ns %s...
28                    CALLING JYTHON FROM CLOJURE(defn make-factory [modulename klassname]  (let [interpreter (PythonInter...
29                     CALLING JYTHON FROM CLOJURE                                 (PT. 2)(defn make-factory  [module klas...
30                           THROW MACROS IN(defmacro pyclass [q-class jtype]  (let [[klass-name module-name] (split-modul...
31                        MAKE-FACTORY (AGAIN)(defn make-factory [module klassname interface] (let [interpreter (PythonInt...
32                   BACK TO THE BEGINNING(defn build-gui [title]  (let [frame (JFrame. title)        button (JButton. "CL...
33                      CONCLUSIONThanks for Your Kind Attention https://github.com/rik0/PyCLJ_Examples https://github.com...
INTEROPERABILITY  CLOJURE      PYTHON      Enrico Franchi
35           OUTLINE   Why Clojure? Why Java?    Clojure from 3000 m.Jython-Clojure interoperabilityClojure-Jython interop...
36                         GENERAL NOTESDuring this presentation some very explicit Java code may be shown.  No ducks were...
37                         GENERAL NOTESDuring this presentation some very explicit Java code may be shown.  No ducks were...
38               JVM LANGUAGESJython               Java                        ?                     JVM         ENRICO FR...
39               JVM LANGUAGESJython               Java                        Clojure                     JVM         ENR...
40                           CLOJURE                       Clojure is Lisp                    Clojure is a good Lisp   Clo...
41                    JVM LANGUAGES                        Jython            Implementation of Python in Java             ...
42                   CLOJURE               ~ Good Parts ~         Functional Programming                  Laziness        ...
43       ATOMIC TYPES           Integers  Floating Point NumbersRatios (3/4 is not 0.75, is ¾)         BigDecimal       St...
44                                    SEQUENCE TYPES                                 Python                   Common Lisp ...
45                        CLOJURE EXAMPLE(defn rember [a lat]  (cond   (empty? lat) ()   (= (first lat) a) (rest lat)   :e...
46                           TAIL CALL OPTIMIZATION(defn multirember [a lat]  (letfn      [(multirember-aux [source sink] ...
47                                      LAZINESS(defn lazy-multirember [a lat]  (letfn      [(multirember-aux [source]    ...
48                       NAMESPACES & MODULES(ns example.namespace)                    (ns example.namespace              ...
49                                   CALLING JAVAJava                         Clojure                               Jython...
50                                                    PROXIES(ns gui-sample  (:import [javax.swing JFrame JButton]        ...
51                                          PROXIES(ns gui-sample  (:import [javax.swing JFrame JButton]           [java.a...
52                                GEN-CLASS(ns example.ClassExample  (:gen-class   :name example.ClassExample   :extends O...
53                              GEN-CLASS (2)(defn show [coll]               (defn -show [coll]  (if (seq coll)           ...
54                         IMPLEMENTING PYOBJECTS                               IN CLOJURE(ns clj.ImmutableList (:gen-clas...
55                         IMPLEMENTING PYOBJECTS                               IN CLOJURE                                ...
56                       IMPLEMENTING PYOBJECTS                            IN CLOJURE (2)(defmacro delegate-to-state [sym]...
57                        IMPLEMENTING PYOBJECTS                             IN CLOJURE (2)(defmacro delegate-to-state [sy...
58                        IMPLEMENTING PYOBJECTS                                                                 print my_...
59                                  CLOJURE RT                             from clojure.lang import RT, Compilersource = (...
60                                 CLOJURE DECORATORimport pyclj@pyclj.clojuredef rember(a, lat):    ’’’(defn rember      ...
61                              IMPLEMENTATIONdef clojure(fn):    """Decorator that substitutes an empty python function w...
62                     IMPLEMENTATION (2)def determine_clojure_namespace(fn):    try:        clj_namespace = fn.__module__...
63                        IMPLEMENTATION (3)def build_clojure_function_object(clj_namespace, fn):    clojure_code = (ns %s...
64                    CALLING JYTHON FROM CLOJURE(defn make-factory [modulename klassname]  (let [interpreter (PythonInter...
65                    CALLING JYTHON FROM CLOJURE(defn make-factory [modulename klassname]  (let [interpreter (PythonInter...
66                     CALLING JYTHON FROM CLOJURE                                 (PT. 2)(defn make-factory  [module klas...
67                           THROW MACROS IN(defmacro pyclass [q-class jtype]  (let [[klass-name module-name] (split-modul...
68                        MAKE-FACTORY (AGAIN)(defn make-factory [module klassname interface] (let [interpreter (PythonInt...
69                   BACK TO THE BEGINNING(defn build-gui [title]  (let [frame (JFrame. title)        button (JButton. "CL...
70                      CONCLUSIONThanks for Your Kind Attention https://github.com/rik0/PyCLJ_Examples https://github.com...
Upcoming SlideShare
Loading in …5
×

Clojure Interoperability

1,156 views

Published on

Some idea

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,156
On SlideShare
0
From Embeds
0
Number of Embeds
7
Actions
Shares
0
Downloads
12
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Clojure Interoperability

  1. 1. INTEROPERABILITY CLOJURE PYTHON Enrico Franchi
  2. 2. 2 OUTLINE Why Clojure? Why Java? Clojure from 3000 m.Jython-Clojure interoperabilityClojure-Jython interoperabilityENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  3. 3. 3 GENERAL NOTESDuring this presentation some very explicit Java code may be shown. No ducks were harmed during the making of this presentation. ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  4. 4. 4 JVM LANGUAGESJython Java ? JVM ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  5. 5. 5 JVM LANGUAGESJython Java Clojure JVM ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  6. 6. 6 CLOJURE Clojure is Lisp Clojure is a good Lisp Clojure has a more functional flavor than Common Lisp;stateful programming is banned unless in very controlled ways Clojure lives on the JVM and perhaps its rejection of state is a reaction to the heavily stateful model of JVM Clojure is not a pure functional language by any means ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  7. 7. 7 JVM LANGUAGES Jython Implementation of Python in Java Jython calls Java ~ Clojure New Programming Languages built on the JVMDesign choices in Clojure reflect design choices of the JVM Interoperability ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  8. 8. 8 CLOJURE ~ Good Parts ~ Functional Programming Laziness Full Macros Multi-MethodsImmutable types, STM & Concurrency Model ~ Bad Parts ~ “Java” ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  9. 9. 9 ATOMIC TYPES Integers Floating Point NumbersRatios (3/4 is not 0.75, is ¾) BigDecimal Strings (“foo”) Booleans (true, false) Nil (nil) Characters (a, b) :keywords regexp’s (#“foo.*”)ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  10. 10. 10 SEQUENCE TYPES Python Common Lisp Clojure Type Syntax Type Syntax Type SyntaxRandom access list [1, 2] vector #(1 2) vector [1 2]sequenceLinked List - No list (1 2) list (1 2)Set set {1, 2} No No set #{1 2}Map dict {1:2, 3:4} hash-table No vector {1 2, 3 4} Clojure collectionsIn Clojure all collections are immutable; implement correspondingall the functions return a new collections – as usual, Java collections interfacesimmutability allows easy data sharing – vector, list List set Set map Map ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  11. 11. 11 CLOJURE EXAMPLE(defn rember [a lat]  (cond   (empty? lat) ()   (= (first lat) a) (rest lat)   :else (cons          (first lat)          (rember a (rest lat)))))(rember 4 (1 2 3 4 5 6 4)); => (1 2 3 5 6 4) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  12. 12. 12 TAIL CALL OPTIMIZATION(defn multirember [a lat]  (letfn      [(multirember-aux [source sink]                   (if (seq source)                     (if (= (first source) a)                       (recur (rest source) sink)                       (recur (rest source)                              (conj sink (first source))))                     sink))]    (multirember-aux lat []))) (take 10(multirember 4 (1 2 3 4 5 6 4)) (multirember 4 (iterate inc 0))); => [1 2 3 5 6] ; Evaluation aborted. ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  13. 13. 13 LAZINESS(defn lazy-multirember [a lat]  (letfn      [(multirember-aux [source]                        (lazy-seq                         (if (seq source)                           (if (= (first source) a)                             (multirember-aux (rest source))                             (cons (first source)                                   (multirember-aux (rest source))))                          ())))]    (multirember-aux lat)))(take 10 (lazy-multirember 4 (iterate inc 0))); => (0 1 2 3 5 6 7 8 9 10)
  14. 14. 14 NAMESPACES & MODULES(ns example.namespace) (ns example.namespace (:require clojure.set))Introduces a new namespace.With def (and defn, …) stuff is (ns example.namespaceadded to namespaces. (:require [clojure.set :as s]))(ns example.namespace (ns example.namespace (:use clojure.string)) (:import [java.util HashMap]))(ns example.namespace (:use [clojure.string :only [capitalize]]))(ns example.namespace (:use [clojure.string :exclude [capitalize]]) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  15. 15. 15 CALLING JAVAJava Clojure Jythonimport app.model.Person; (import [app.model Person]) from app.model import Personnew Person() (new Person) Person() (Person.)person.getFullName() (. getFullName person) person.getFullName() (.getFullName person)Locale.JAPAN (. Locale JAPAN) Locale.JAPAN Locale/JAPANInteger.valueOf(“42”) (. Integer valueOf "42") java.lang.Integer.valueOf(42) (Integer/valueOf “42”) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  16. 16. 16 PROXIES(ns gui-sample  (:import [javax.swing JFrame JButton] (gui-sample/build-gui           [java.awt.event ActionListener])) "Rock & Roll"(defn build-gui [title message] "Hello, world!”)  (let [frame (JFrame. title)        button (JButton. "CLICK")]    (.addActionListener button                        (proxy [ActionListener] []                          (actionPerformed [evt]                                           (println message))))    (.. frame getContentPane (add button))    (.pack frame)    (.setVisible frame true)    frame)) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  17. 17. 17 PROXIES(ns gui-sample  (:import [javax.swing JFrame JButton]           [java.awt.event ActionListener]))(defn build-gui [title message]  (let [frame (JFrame. title)        button (JButton. "CLICK")        px (proxy [ActionListener] []                          (actionPerformed [evt]                                           (println message)))]    (.addActionListener button px)    (.. frame getContentPane (add button))    (.pack frame)    (.setVisible frame true) px))    (update-proxy p {"actionPerformed" (fn [this evt] (println "foo!"))}) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  18. 18. 18 GEN-CLASS(ns example.ClassExample  (:gen-class   :name example.ClassExample   :extends Object   :implements []   :methods [ [foo [java.util.Collection] int]             ^{:static true} [show [java.util.Collection] void]])  (:import (java.util Collection))) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  19. 19. 19 GEN-CLASS (2)(defn show [coll] (defn -show [coll]  (if (seq coll)   (show coll))    (do      (print (first coll)) (defn -foo [this coll]      (recur (rest coll)))   (let [coll (seq coll)]    (println "")))     (if coll (count coll) -1))) >>> import example >>> example.ClassExample.show([1, 2, 3]) 123 >>> ce = example.ClassExample() >>> ce.foo([1, 2, 3]) 3
  20. 20. 20 IMPLEMENTING PYOBJECTS IN CLOJURE import clj(ns clj.ImmutableList (:gen-class py_list = [a, b, c] :name clj.ImmutableList my_list = clj.ImmutableList(py_list) :extends org.python.core.PyObject :implements [clojure.lang.IPersistentList] :state state :init init :constructors {[java.util.Collection], []}) (:import [org.python.core PyObject PyInteger Py]))(defn -init [coll] [[coll] (apply list coll)]) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  21. 21. 21 IMPLEMENTING PYOBJECTS IN CLOJURE (2)(defmacro delegate-to-state [sym] (defn -cons [this other] `(defn ~(symbol (str "-" sym)) (cons (.state this) other)) [this#] (~sym (.state this#)))) (defn -equiv [this other] print(.state this) other)) (= my_list.peek()(delegate-to-state peek) print my_list.pop()(delegate-to-state pop) print my_list.count()(delegate-to-state count) print my_list.empty()(delegate-to-state empty) print my_list.seq()(delegate-to-state seq) print my_list.cons(d) print my_list.equiv(py_list) print my_list.equiv([a, b, c]) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  22. 22. 22 IMPLEMENTING PYOBJECTS print my_list[0] IN CLOJURE (3) print my_list[1] print my_list[2](defn -__finditem__ [this index] print my_list[2.4] (let [index (if (instance? Number index) index try: (Py/tojava index Number))] print my_list[3] except IndexError, e: (try print e (Py/java2py (nth (.state this) index)) try: (catch IndexOutOfBoundsException e print my_list[a] (throw (Py/IndexError (.toString e))))))) except TypeError, e: print e try: my_list[0] = 1 except TypeError, e: print e ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  23. 23. 23 CLOJURE RT from clojure.lang import RT, Compilersource = (ns rember) Compiler.load(java.io.StringReader(source))(defn rember [a lat] rember = RT.var(rember, rember) (cond print rember.invoke(2, range(4)) (empty? lat) () (= (first lat) a) (rest lat) :else (cons (first lat) (rember a (rest lat))))) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  24. 24. 24 CLOJURE DECORATORimport pyclj@pyclj.clojuredef rember(a, lat):    ’’’(defn rember "Remove first occurrence of a from lat" [a lat] (cond (empty? lat) () (= (first lat) a) (rest lat) :else (cons (first lat) (rember a (rest lat)))))’’’if __name__ == __main__:    print rember(2, range(4))    help(rember) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  25. 25. 25 IMPLEMENTATIONdef clojure(fn):    """Decorator that substitutes an empty python function with clojure in the doc with a callable which delegates to the clojure function. """    clj_namespace = determine_clojure_namespace(fn)    clojure_fnc = build_clojure_function_object(clj_namespace, fn)    fn.__doc__ = get_docs(clojure_fnc)    def aux(*args):        return clojure_fnc.invoke(*args)    functools.update_wrapper(aux, fn)    return aux ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  26. 26. 26 IMPLEMENTATION (2)def determine_clojure_namespace(fn):    try:        clj_namespace = fn.__module__    except AttributeError:        clj_namespace = user    return clj_namespacedef get_docs(clojure_fnc):    meta = clojure_fnc.meta()    return meta.get(Keyword.intern(doc)) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  27. 27. 27 IMPLEMENTATION (3)def build_clojure_function_object(clj_namespace, fn):    clojure_code = (ns %s)n%s % (        clj_namespace,        fn.__doc__)    clojure_compile_string(clojure_code)    clojure_fnc = RT.var(clj_namespace, fn.func_name)    return clojure_fnc ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  28. 28. 28 CALLING JYTHON FROM CLOJURE(defn make-factory [modulename klassname]  (let [interpreter (PythonInterpreter.) class SpamAndEggs(object):         import-command (str-join " " ["from" modulename     def __init__(self, eggs): "import" klassname])]         self.eggs = eggs    (.exec interpreter import-command)    (.get interpreter klassname))) hasSpam(self):     def         return True(def spam-and-eggs (make-factory "example" "SpamAndEggs"))     def getEggs(self):(def inst (.__call__ spam-and-eggs (Py/java2py 1)))         return self.eggs(println inst)     def __repr__(self):(println (.invoke inst "hasSpam"))         return Spam and %s eggs. % self.eggs
  29. 29. 29 CALLING JYTHON FROM CLOJURE (PT. 2)(defn make-factory  [module klassname]  (let [interpreter (PythonInterpreter.)        import-command (str-join " " ["from" module "import" klassname])]    (.exec interpreter import-command)    (let [klass (.get interpreter klassname)]      (fn [& args]        (.__call__ klass          (into-array PyObject            (map #(Py/java2py %) args)))))))(def spam-and-eggs (make-factory "example" "SpamAndEggs"))(def inst (spam-and-eggs 1))
  30. 30. 30 THROW MACROS IN(defmacro pyclass [q-class jtype]  (let [[klass-name module-name] (split-module-and-class q-class)]    `(def ~(symbol klass-name)      (make-factory ~(str module-name) ~(str klass-name) ~jtype))))(pyclass example.PrintSomething java.awt.event.ActionListener)(def evt-printer (PrintSomething)) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  31. 31. 31 MAKE-FACTORY (AGAIN)(defn make-factory [module klassname interface] (let [interpreter (PythonInterpreter.) import-command (str-join " " ["from" module "import" klassname])] (.exec interpreter import-command) (let [klass (.get interpreter klassname)] (fn [& args] (.__tojava__ (.__call__ klass (into-array PyObject (map #(Py/java2py %) args))) interface))))) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  32. 32. 32 BACK TO THE BEGINNING(defn build-gui [title]  (let [frame (JFrame. title)        button (JButton. "CLICK")]    (.addActionListener button (PrintSomething))    (.. frame getContentPane (add button))    (.pack frame)    (.setVisible frame true)    frame)) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  33. 33. 33 CONCLUSIONThanks for Your Kind Attention https://github.com/rik0/PyCLJ_Examples https://github.com/rik0/pyclj ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  34. 34. INTEROPERABILITY CLOJURE PYTHON Enrico Franchi
  35. 35. 35 OUTLINE Why Clojure? Why Java? Clojure from 3000 m.Jython-Clojure interoperabilityClojure-Jython interoperabilityENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  36. 36. 36 GENERAL NOTESDuring this presentation some very explicit Java code may be shown. No ducks were harmed during the making of this presentation. ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  37. 37. 37 GENERAL NOTESDuring this presentation some very explicit Java code may be shown. No ducks were harmed during the making of this presentation. ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  38. 38. 38 JVM LANGUAGESJython Java ? JVM ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  39. 39. 39 JVM LANGUAGESJython Java Clojure JVM ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  40. 40. 40 CLOJURE Clojure is Lisp Clojure is a good Lisp Clojure has a more functional flavor than Common Lisp;stateful programming is banned unless in very controlled ways Clojure lives on the JVM and perhaps its rejection of state is a reaction to the heavily stateful model of JVM Clojure is not a pure functional language by any means ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  41. 41. 41 JVM LANGUAGES Jython Implementation of Python in Java Jython calls Java ~ Clojure New Programming Languages built on the JVMDesign choices in Clojure reflect design choices of the JVM Interoperability ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  42. 42. 42 CLOJURE ~ Good Parts ~ Functional Programming Laziness Full Macros Multi-MethodsImmutable types, STM & Concurrency Model ~ Bad Parts ~ “Java” ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  43. 43. 43 ATOMIC TYPES Integers Floating Point NumbersRatios (3/4 is not 0.75, is ¾) BigDecimal Strings (“foo”) Booleans (true, false) Nil (nil) Characters (a, b) :keywords regexp’s (#“foo.*”)ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  44. 44. 44 SEQUENCE TYPES Python Common Lisp Clojure Type Syntax Type Syntax Type SyntaxRandom access list [1, 2] vector #(1 2) vector [1 2]sequenceLinked List - No list (1 2) list (1 2)Set set {1, 2} No No set #{1 2}Map dict {1:2, 3:4} hash-table No vector {1 2, 3 4} Clojure collectionsIn Clojure all collections are immutable; implement correspondingall the functions return a new collections – as usual, Java collections interfacesimmutability allows easy data sharing – vector, list List set Set map Map ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  45. 45. 45 CLOJURE EXAMPLE(defn rember [a lat]  (cond   (empty? lat) ()   (= (first lat) a) (rest lat)   :else (cons          (first lat)          (rember a (rest lat)))))(rember 4 (1 2 3 4 5 6 4)); => (1 2 3 5 6 4) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  46. 46. 46 TAIL CALL OPTIMIZATION(defn multirember [a lat]  (letfn      [(multirember-aux [source sink]                   (if (seq source)                     (if (= (first source) a)                       (recur (rest source) sink)                       (recur (rest source)                              (conj sink (first source))))                     sink))]    (multirember-aux lat []))) (take 10(multirember 4 (1 2 3 4 5 6 4)) (multirember 4 (iterate inc 0))); => [1 2 3 5 6] ; Evaluation aborted. ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  47. 47. 47 LAZINESS(defn lazy-multirember [a lat]  (letfn      [(multirember-aux [source]                        (lazy-seq                         (if (seq source)                           (if (= (first source) a)                             (multirember-aux (rest source))                             (cons (first source)                                   (multirember-aux (rest source))))                          ())))]    (multirember-aux lat)))(take 10 (lazy-multirember 4 (iterate inc 0))); => (0 1 2 3 5 6 7 8 9 10)
  48. 48. 48 NAMESPACES & MODULES(ns example.namespace) (ns example.namespace (:require clojure.set))Introduces a new namespace.With def (and defn, …) stuff is (ns example.namespaceadded to namespaces. (:require [clojure.set :as s]))(ns example.namespace (ns example.namespace (:use clojure.string)) (:import [java.util HashMap]))(ns example.namespace (:use [clojure.string :only [capitalize]]))(ns example.namespace (:use [clojure.string :exclude [capitalize]]) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  49. 49. 49 CALLING JAVAJava Clojure Jythonimport app.model.Person; (import [app.model Person]) from app.model import Personnew Person() (new Person) Person() (Person.)person.getFullName() (. getFullName person) person.getFullName() (.getFullName person)Locale.JAPAN (. Locale JAPAN) Locale.JAPAN Locale/JAPANInteger.valueOf(“42”) (. Integer valueOf "42") java.lang.Integer.valueOf(42) (Integer/valueOf “42”) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  50. 50. 50 PROXIES(ns gui-sample  (:import [javax.swing JFrame JButton] (gui-sample/build-gui           [java.awt.event ActionListener])) "Rock & Roll"(defn build-gui [title message] "Hello, world!”)  (let [frame (JFrame. title)        button (JButton. "CLICK")]    (.addActionListener button                        (proxy [ActionListener] []                          (actionPerformed [evt]                                           (println message))))    (.. frame getContentPane (add button))    (.pack frame)    (.setVisible frame true)    frame)) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  51. 51. 51 PROXIES(ns gui-sample  (:import [javax.swing JFrame JButton]           [java.awt.event ActionListener]))(defn build-gui [title message]  (let [frame (JFrame. title)        button (JButton. "CLICK")        px (proxy [ActionListener] []                          (actionPerformed [evt]                                           (println message)))]    (.addActionListener button px)    (.. frame getContentPane (add button))    (.pack frame)    (.setVisible frame true) px))    (update-proxy p {"actionPerformed" (fn [this evt] (println "foo!"))}) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  52. 52. 52 GEN-CLASS(ns example.ClassExample  (:gen-class   :name example.ClassExample   :extends Object   :implements []   :methods [ [foo [java.util.Collection] int]             ^{:static true} [show [java.util.Collection] void]])  (:import (java.util Collection))) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  53. 53. 53 GEN-CLASS (2)(defn show [coll] (defn -show [coll]  (if (seq coll)   (show coll))    (do      (print (first coll)) (defn -foo [this coll]      (recur (rest coll)))   (let [coll (seq coll)]    (println "")))     (if coll (count coll) -1))) >>> import example >>> example.ClassExample.show([1, 2, 3]) 123 >>> ce = example.ClassExample() >>> ce.foo([1, 2, 3]) 3
  54. 54. 54 IMPLEMENTING PYOBJECTS IN CLOJURE(ns clj.ImmutableList (:gen-class :name clj.ImmutableList :extends org.python.core.PyObject :implements [clojure.lang.IPersistentList] :state state :init init :constructors {[java.util.Collection], []}) (:import [org.python.core PyObject PyInteger Py]))(defn -init [coll] [[coll] (apply list coll)]) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  55. 55. 55 IMPLEMENTING PYOBJECTS IN CLOJURE import clj(ns clj.ImmutableList (:gen-class py_list = [a, b, c] :name clj.ImmutableList my_list = clj.ImmutableList(py_list) :extends org.python.core.PyObject :implements [clojure.lang.IPersistentList] :state state :init init :constructors {[java.util.Collection], []}) (:import [org.python.core PyObject PyInteger Py]))(defn -init [coll] [[coll] (apply list coll)]) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  56. 56. 56 IMPLEMENTING PYOBJECTS IN CLOJURE (2)(defmacro delegate-to-state [sym] (defn -cons [this other] `(defn ~(symbol (str "-" sym)) (cons (.state this) other)) [this#] (~sym (.state this#)))) (defn -equiv [this other] (= (.state this) other))(delegate-to-state peek)(delegate-to-state pop)(delegate-to-state count)(delegate-to-state empty)(delegate-to-state seq) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  57. 57. 57 IMPLEMENTING PYOBJECTS IN CLOJURE (2)(defmacro delegate-to-state [sym] (defn -cons [this other] `(defn ~(symbol (str "-" sym)) (cons (.state this) other)) [this#] (~sym (.state this#)))) (defn -equiv [this other] print(.state this) other)) (= my_list.peek()(delegate-to-state peek) print my_list.pop()(delegate-to-state pop) print my_list.count()(delegate-to-state count) print my_list.empty()(delegate-to-state empty) print my_list.seq()(delegate-to-state seq) print my_list.cons(d) print my_list.equiv(py_list) print my_list.equiv([a, b, c]) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  58. 58. 58 IMPLEMENTING PYOBJECTS print my_list[0] IN CLOJURE (3) print my_list[1] print my_list[2](defn -__finditem__ [this index] print my_list[2.4] (let [index (if (instance? Number index) index try: (Py/tojava index Number))] print my_list[3] except IndexError, e: (try print e (Py/java2py (nth (.state this) index)) try: (catch IndexOutOfBoundsException e print my_list[a] (throw (Py/IndexError (.toString e))))))) except TypeError, e: print e try: my_list[0] = 1 except TypeError, e: print e ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  59. 59. 59 CLOJURE RT from clojure.lang import RT, Compilersource = (ns rember) Compiler.load(java.io.StringReader(source))(defn rember [a lat] rember = RT.var(rember, rember) (cond print rember.invoke(2, range(4)) (empty? lat) () (= (first lat) a) (rest lat) :else (cons (first lat) (rember a (rest lat))))) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  60. 60. 60 CLOJURE DECORATORimport pyclj@pyclj.clojuredef rember(a, lat):    ’’’(defn rember "Remove first occurrence of a from lat" [a lat] (cond (empty? lat) () (= (first lat) a) (rest lat) :else (cons (first lat) (rember a (rest lat)))))’’’if __name__ == __main__:    print rember(2, range(4))    help(rember) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  61. 61. 61 IMPLEMENTATIONdef clojure(fn):    """Decorator that substitutes an empty python function with clojure in the doc with a callable which delegates to the clojure function. """    clj_namespace = determine_clojure_namespace(fn)    clojure_fnc = build_clojure_function_object(clj_namespace, fn)    fn.__doc__ = get_docs(clojure_fnc)    def aux(*args):        return clojure_fnc.invoke(*args)    functools.update_wrapper(aux, fn)    return aux ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  62. 62. 62 IMPLEMENTATION (2)def determine_clojure_namespace(fn):    try:        clj_namespace = fn.__module__    except AttributeError:        clj_namespace = user    return clj_namespacedef get_docs(clojure_fnc):    meta = clojure_fnc.meta()    return meta.get(Keyword.intern(doc)) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  63. 63. 63 IMPLEMENTATION (3)def build_clojure_function_object(clj_namespace, fn):    clojure_code = (ns %s)n%s % (        clj_namespace,        fn.__doc__)    clojure_compile_string(clojure_code)    clojure_fnc = RT.var(clj_namespace, fn.func_name)    return clojure_fnc ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  64. 64. 64 CALLING JYTHON FROM CLOJURE(defn make-factory [modulename klassname]  (let [interpreter (PythonInterpreter.)         import-command (str-join " " ["from" modulename "import" klassname])]    (.exec interpreter import-command)    (.get interpreter klassname)))(def spam-and-eggs (make-factory "example" "SpamAndEggs"))(def inst (.__call__ spam-and-eggs (Py/java2py 1)))(println inst)(println (.invoke inst "hasSpam"))
  65. 65. 65 CALLING JYTHON FROM CLOJURE(defn make-factory [modulename klassname]  (let [interpreter (PythonInterpreter.) class SpamAndEggs(object):         import-command (str-join " " ["from" modulename     def __init__(self, eggs): "import" klassname])]         self.eggs = eggs    (.exec interpreter import-command)    (.get interpreter klassname))) hasSpam(self):     def         return True(def spam-and-eggs (make-factory "example" "SpamAndEggs"))     def getEggs(self):(def inst (.__call__ spam-and-eggs (Py/java2py 1)))         return self.eggs(println inst)     def __repr__(self):(println (.invoke inst "hasSpam"))         return Spam and %s eggs. % self.eggs
  66. 66. 66 CALLING JYTHON FROM CLOJURE (PT. 2)(defn make-factory  [module klassname]  (let [interpreter (PythonInterpreter.)        import-command (str-join " " ["from" module "import" klassname])]    (.exec interpreter import-command)    (let [klass (.get interpreter klassname)]      (fn [& args]        (.__call__ klass          (into-array PyObject            (map #(Py/java2py %) args)))))))(def spam-and-eggs (make-factory "example" "SpamAndEggs"))(def inst (spam-and-eggs 1))
  67. 67. 67 THROW MACROS IN(defmacro pyclass [q-class jtype]  (let [[klass-name module-name] (split-module-and-class q-class)]    `(def ~(symbol klass-name)      (make-factory ~(str module-name) ~(str klass-name) ~jtype))))(pyclass example.PrintSomething java.awt.event.ActionListener)(def evt-printer (PrintSomething)) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  68. 68. 68 MAKE-FACTORY (AGAIN)(defn make-factory [module klassname interface] (let [interpreter (PythonInterpreter.) import-command (str-join " " ["from" module "import" klassname])] (.exec interpreter import-command) (let [klass (.get interpreter klassname)] (fn [& args] (.__tojava__ (.__call__ klass (into-array PyObject (map #(Py/java2py %) args))) interface))))) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  69. 69. 69 BACK TO THE BEGINNING(defn build-gui [title]  (let [frame (JFrame. title)        button (JButton. "CLICK")]    (.addActionListener button (PrintSomething))    (.. frame getContentPane (add button))    (.pack frame)    (.setVisible frame true)    frame)) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  70. 70. 70 CONCLUSIONThanks for Your Kind Attention https://github.com/rik0/PyCLJ_Examples https://github.com/rik0/pyclj ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>

×