SlideShare a Scribd company logo
1 of 70
Download to read offline
INTEROPERABILITY
  CLOJURE      PYTHON
      Enrico Franchi
2



           OUTLINE


   Why Clojure? Why Java?
    Clojure from 3000 m.
Jython-Clojure interoperability
Clojure-Jython interoperability




ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
3



                         GENERAL NOTES




During 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



               JVM LANGUAGES




Jython               Java                        ?



                     JVM


         ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
5



               JVM LANGUAGES




Jython               Java                        Clojure



                     JVM


         ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
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



                    JVM LANGUAGES


                        Jython
            Implementation of Python in Java
                   Jython calls Java


                             ~
                          Clojure
     New Programming Languages built on the JVM
Design choices in Clojure reflect design choices of the JVM
                      Interoperability




              ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
8



                   CLOJURE


               ~ Good Parts ~

         Functional Programming
                  Laziness
                Full Macros
              Multi-Methods
Immutable types, STM & Concurrency Model

                ~ Bad Parts ~

                     “Java”


       ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
9



       ATOMIC TYPES


           Integers
  Floating Point Numbers
Ratios (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



                                    SEQUENCE TYPES


                                 Python                   Common Lisp                   Clojure
                        Type          Syntax       Type          Syntax    Type             Syntax
Random access           list          [1, 2]       vector        #(1 2)    vector           [1 2]
sequence
Linked 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 collections
In Clojure all collections are immutable;
                                                                  implement corresponding
all the functions return a new collections – as usual,
                                                                  Java collections interfaces
immutability allows easy data sharing –
                                                                  vector, list List
                                                                  set             Set
                                                                  map             Map
                               ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
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



                           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



                                      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



                       NAMESPACES & MODULES


(ns example.namespace)                    (ns example.namespace
                                              (:require clojure.set))
Introduces a new namespace.
With def (and defn, …) stuff is           (ns example.namespace
added 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



                                   CALLING JAVA


Java                         Clojure                               Jython
import app.model.Person;     (import [app.model Person])           from app.model import
                                                                   Person
new Person()                 (new Person)                          Person()
                             (Person.)
person.getFullName()         (. getFullName person)                person.getFullName()
                             (.getFullName person)
Locale.JAPAN                 (. Locale JAPAN)                      Locale.JAPAN
                             Locale/JAPAN
Integer.valueOf(“42”)        (. Integer valueOf "42")              java.lang.Integer.valueOf('42')
                             (Integer/valueOf “42”)




                           ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
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



                                          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



                                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



                              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


                         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


                        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


                        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



                                  CLOJURE RT


                             from clojure.lang import RT, Compiler
source = '''
(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



                                 CLOJURE DECORATOR
import pyclj

@pyclj.clojure
def 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



                              IMPLEMENTATION

def 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



                     IMPLEMENTATION (2)


def determine_clojure_namespace(fn):
    try:
        clj_namespace = fn.__module__
    except AttributeError:
        clj_namespace = 'user'
    return clj_namespace

def get_docs(clojure_fnc):
    meta = clojure_fnc.meta()
    return meta.get(Keyword.intern('doc'))


                   ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
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



                    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


                     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



                           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



                        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



                   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



                      CONCLUSION




Thanks for Your Kind Attention

 https://github.com/rik0/PyCLJ_Examples
 https://github.com/rik0/pyclj

              ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
INTEROPERABILITY
  CLOJURE      PYTHON
      Enrico Franchi
35



           OUTLINE


   Why Clojure? Why Java?
    Clojure from 3000 m.
Jython-Clojure interoperability
Clojure-Jython interoperability




ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
36



                         GENERAL NOTES




During 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



                         GENERAL NOTES




During 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



               JVM LANGUAGES




Jython               Java                        ?



                     JVM


         ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
39



               JVM LANGUAGES




Jython               Java                        Clojure



                     JVM


         ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
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



                    JVM LANGUAGES


                        Jython
            Implementation of Python in Java
                   Jython calls Java


                             ~
                          Clojure
     New Programming Languages built on the JVM
Design choices in Clojure reflect design choices of the JVM
                      Interoperability




              ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
42



                   CLOJURE


               ~ Good Parts ~

         Functional Programming
                  Laziness
                Full Macros
              Multi-Methods
Immutable types, STM & Concurrency Model

                ~ Bad Parts ~

                     “Java”


       ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
43



       ATOMIC TYPES


           Integers
  Floating Point Numbers
Ratios (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



                                    SEQUENCE TYPES


                                 Python                   Common Lisp                   Clojure
                        Type          Syntax       Type          Syntax    Type             Syntax
Random access           list          [1, 2]       vector        #(1 2)    vector           [1 2]
sequence
Linked 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 collections
In Clojure all collections are immutable;
                                                                  implement corresponding
all the functions return a new collections – as usual,
                                                                  Java collections interfaces
immutability allows easy data sharing –
                                                                  vector, list List
                                                                  set             Set
                                                                  map             Map
                               ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
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



                           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



                                      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



                       NAMESPACES & MODULES


(ns example.namespace)                    (ns example.namespace
                                              (:require clojure.set))
Introduces a new namespace.
With def (and defn, …) stuff is           (ns example.namespace
added 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



                                   CALLING JAVA


Java                         Clojure                               Jython
import app.model.Person;     (import [app.model Person])           from app.model import
                                                                   Person
new Person()                 (new Person)                          Person()
                             (Person.)
person.getFullName()         (. getFullName person)                person.getFullName()
                             (.getFullName person)
Locale.JAPAN                 (. Locale JAPAN)                      Locale.JAPAN
                             Locale/JAPAN
Integer.valueOf(“42”)        (. Integer valueOf "42")              java.lang.Integer.valueOf('42')
                             (Integer/valueOf “42”)




                           ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
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



                                          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



                                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



                              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


                         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


                         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


                       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


                        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


                        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



                                  CLOJURE RT


                             from clojure.lang import RT, Compiler
source = '''
(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



                                 CLOJURE DECORATOR
import pyclj

@pyclj.clojure
def 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



                              IMPLEMENTATION

def 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



                     IMPLEMENTATION (2)


def determine_clojure_namespace(fn):
    try:
        clj_namespace = fn.__module__
    except AttributeError:
        clj_namespace = 'user'
    return clj_namespace

def get_docs(clojure_fnc):
    meta = clojure_fnc.meta()
    return meta.get(Keyword.intern('doc'))


                   ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
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



                    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



                    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


                     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



                           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



                        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



                   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



                      CONCLUSION




Thanks for Your Kind Attention

 https://github.com/rik0/PyCLJ_Examples
 https://github.com/rik0/pyclj

              ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>

More Related Content

What's hot

Clojure beasts-euroclj-2014
Clojure beasts-euroclj-2014Clojure beasts-euroclj-2014
Clojure beasts-euroclj-2014Renzo Borgatti
 
Write Your Own JVM Compiler
Write Your Own JVM CompilerWrite Your Own JVM Compiler
Write Your Own JVM CompilerErin Dees
 
Effective Java - Enum and Annotations
Effective Java - Enum and AnnotationsEffective Java - Enum and Annotations
Effective Java - Enum and AnnotationsRoshan Deniyage
 
Concurrent programming with Celluloid (MWRC 2012)
Concurrent programming with Celluloid (MWRC 2012)Concurrent programming with Celluloid (MWRC 2012)
Concurrent programming with Celluloid (MWRC 2012)tarcieri
 
Denis Lebedev, Swift
Denis  Lebedev, SwiftDenis  Lebedev, Swift
Denis Lebedev, SwiftYandex
 
Playfulness at Work
Playfulness at WorkPlayfulness at Work
Playfulness at WorkErin Dees
 
Thnad's Revenge
Thnad's RevengeThnad's Revenge
Thnad's RevengeErin Dees
 
Cocoa Design Patterns in Swift
Cocoa Design Patterns in SwiftCocoa Design Patterns in Swift
Cocoa Design Patterns in SwiftMichele Titolo
 
Swift Programming Language
Swift Programming LanguageSwift Programming Language
Swift Programming LanguageGiuseppe Arici
 
JRuby, Not Just For Hard-Headed Pragmatists Anymore
JRuby, Not Just For Hard-Headed Pragmatists AnymoreJRuby, Not Just For Hard-Headed Pragmatists Anymore
JRuby, Not Just For Hard-Headed Pragmatists AnymoreErin Dees
 
Latest C Interview Questions and Answers
Latest C Interview Questions and AnswersLatest C Interview Questions and Answers
Latest C Interview Questions and AnswersDaisyWatson5
 
Your Own Metric System
Your Own Metric SystemYour Own Metric System
Your Own Metric SystemErin Dees
 

What's hot (20)

Perl intro
Perl introPerl intro
Perl intro
 
JavaFXScript
JavaFXScriptJavaFXScript
JavaFXScript
 
Swift Introduction
Swift IntroductionSwift Introduction
Swift Introduction
 
Clojure 7-Languages
Clojure 7-LanguagesClojure 7-Languages
Clojure 7-Languages
 
Clojure beasts-euroclj-2014
Clojure beasts-euroclj-2014Clojure beasts-euroclj-2014
Clojure beasts-euroclj-2014
 
Java For Automation
Java   For AutomationJava   For Automation
Java For Automation
 
Write Your Own JVM Compiler
Write Your Own JVM CompilerWrite Your Own JVM Compiler
Write Your Own JVM Compiler
 
Effective Java - Enum and Annotations
Effective Java - Enum and AnnotationsEffective Java - Enum and Annotations
Effective Java - Enum and Annotations
 
Concurrent programming with Celluloid (MWRC 2012)
Concurrent programming with Celluloid (MWRC 2012)Concurrent programming with Celluloid (MWRC 2012)
Concurrent programming with Celluloid (MWRC 2012)
 
Python
PythonPython
Python
 
Meta Object Protocols
Meta Object ProtocolsMeta Object Protocols
Meta Object Protocols
 
Denis Lebedev, Swift
Denis  Lebedev, SwiftDenis  Lebedev, Swift
Denis Lebedev, Swift
 
Playfulness at Work
Playfulness at WorkPlayfulness at Work
Playfulness at Work
 
Thnad's Revenge
Thnad's RevengeThnad's Revenge
Thnad's Revenge
 
Cocoa Design Patterns in Swift
Cocoa Design Patterns in SwiftCocoa Design Patterns in Swift
Cocoa Design Patterns in Swift
 
Swift 2
Swift 2Swift 2
Swift 2
 
Swift Programming Language
Swift Programming LanguageSwift Programming Language
Swift Programming Language
 
JRuby, Not Just For Hard-Headed Pragmatists Anymore
JRuby, Not Just For Hard-Headed Pragmatists AnymoreJRuby, Not Just For Hard-Headed Pragmatists Anymore
JRuby, Not Just For Hard-Headed Pragmatists Anymore
 
Latest C Interview Questions and Answers
Latest C Interview Questions and AnswersLatest C Interview Questions and Answers
Latest C Interview Questions and Answers
 
Your Own Metric System
Your Own Metric SystemYour Own Metric System
Your Own Metric System
 

Viewers also liked

Pyimproved
PyimprovedPyimproved
Pyimprovedrik0
 
Game theory
Game theoryGame theory
Game theoryrik0
 
Social Network Analysis
Social Network AnalysisSocial Network Analysis
Social Network Analysisrik0
 
Python intro
Python introPython intro
Python introrik0
 
Social choice
Social choiceSocial choice
Social choicerik0
 
Regular expressions in Python
Regular expressions in PythonRegular expressions in Python
Regular expressions in PythonSujith Kumar
 
Complex and Social Network Analysis in Python
Complex and Social Network Analysis in PythonComplex and Social Network Analysis in Python
Complex and Social Network Analysis in Pythonrik0
 

Viewers also liked (7)

Pyimproved
PyimprovedPyimproved
Pyimproved
 
Game theory
Game theoryGame theory
Game theory
 
Social Network Analysis
Social Network AnalysisSocial Network Analysis
Social Network Analysis
 
Python intro
Python introPython intro
Python intro
 
Social choice
Social choiceSocial choice
Social choice
 
Regular expressions in Python
Regular expressions in PythonRegular expressions in Python
Regular expressions in Python
 
Complex and Social Network Analysis in Python
Complex and Social Network Analysis in PythonComplex and Social Network Analysis in Python
Complex and Social Network Analysis in Python
 

Similar to Clojure Interoperability

Clojure made-simple - John Stevenson
Clojure made-simple - John StevensonClojure made-simple - John Stevenson
Clojure made-simple - John StevensonJAX London
 
Introduction to clojure
Introduction to clojureIntroduction to clojure
Introduction to clojureAbbas Raza
 
Clojure - A new Lisp
Clojure - A new LispClojure - A new Lisp
Clojure - A new Lispelliando dias
 
Getting started with Clojure
Getting started with ClojureGetting started with Clojure
Getting started with ClojureJohn Stevenson
 
DevNexus 2018: Learn Java 8, lambdas and functional programming
DevNexus 2018: Learn Java 8, lambdas and functional programmingDevNexus 2018: Learn Java 8, lambdas and functional programming
DevNexus 2018: Learn Java 8, lambdas and functional programmingHenri Tremblay
 
Clojure Intro
Clojure IntroClojure Intro
Clojure Introthnetos
 
Clojure - A practical LISP for the JVM
Clojure - A practical LISP for the JVMClojure - A practical LISP for the JVM
Clojure - A practical LISP for the JVMMatthias Nüßler
 
(map Clojure everyday-tasks)
(map Clojure everyday-tasks)(map Clojure everyday-tasks)
(map Clojure everyday-tasks)Jacek Laskowski
 
What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)Pavlo Baron
 
Scala clojure techday_2011
Scala clojure techday_2011Scala clojure techday_2011
Scala clojure techday_2011Thadeu Russo
 
Clojure made simple - Lightning talk
Clojure made simple - Lightning talkClojure made simple - Lightning talk
Clojure made simple - Lightning talkJohn Stevenson
 
Clojure 1.1 And Beyond
Clojure 1.1 And BeyondClojure 1.1 And Beyond
Clojure 1.1 And BeyondMike Fogus
 
From Java To Clojure (English version)
From Java To Clojure (English version)From Java To Clojure (English version)
From Java To Clojure (English version)Kent Ohashi
 
Clojure and The Robot Apocalypse
Clojure and The Robot ApocalypseClojure and The Robot Apocalypse
Clojure and The Robot Apocalypseelliando dias
 
Clojure made really really simple
Clojure made really really simpleClojure made really really simple
Clojure made really really simpleJohn Stevenson
 
From Lisp to Clojure/Incanter and RAn Introduction
From Lisp to Clojure/Incanter and RAn IntroductionFrom Lisp to Clojure/Incanter and RAn Introduction
From Lisp to Clojure/Incanter and RAn Introductionelliando dias
 
From Java to Parellel Clojure - Clojure South 2019
From Java to Parellel Clojure - Clojure South 2019From Java to Parellel Clojure - Clojure South 2019
From Java to Parellel Clojure - Clojure South 2019Leonardo Borges
 

Similar to Clojure Interoperability (20)

Clojure made-simple - John Stevenson
Clojure made-simple - John StevensonClojure made-simple - John Stevenson
Clojure made-simple - John Stevenson
 
Introduction to clojure
Introduction to clojureIntroduction to clojure
Introduction to clojure
 
Clojure - A new Lisp
Clojure - A new LispClojure - A new Lisp
Clojure - A new Lisp
 
Getting started with Clojure
Getting started with ClojureGetting started with Clojure
Getting started with Clojure
 
DevNexus 2018: Learn Java 8, lambdas and functional programming
DevNexus 2018: Learn Java 8, lambdas and functional programmingDevNexus 2018: Learn Java 8, lambdas and functional programming
DevNexus 2018: Learn Java 8, lambdas and functional programming
 
Clojure Intro
Clojure IntroClojure Intro
Clojure Intro
 
Clojure - A practical LISP for the JVM
Clojure - A practical LISP for the JVMClojure - A practical LISP for the JVM
Clojure - A practical LISP for the JVM
 
(map Clojure everyday-tasks)
(map Clojure everyday-tasks)(map Clojure everyday-tasks)
(map Clojure everyday-tasks)
 
55j7
55j755j7
55j7
 
What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)
 
Pune Clojure Course Outline
Pune Clojure Course OutlinePune Clojure Course Outline
Pune Clojure Course Outline
 
Scala clojure techday_2011
Scala clojure techday_2011Scala clojure techday_2011
Scala clojure techday_2011
 
Clojure made simple - Lightning talk
Clojure made simple - Lightning talkClojure made simple - Lightning talk
Clojure made simple - Lightning talk
 
Clojure 1.1 And Beyond
Clojure 1.1 And BeyondClojure 1.1 And Beyond
Clojure 1.1 And Beyond
 
From Java To Clojure (English version)
From Java To Clojure (English version)From Java To Clojure (English version)
From Java To Clojure (English version)
 
Clojure and The Robot Apocalypse
Clojure and The Robot ApocalypseClojure and The Robot Apocalypse
Clojure and The Robot Apocalypse
 
Clojure intro
Clojure introClojure intro
Clojure intro
 
Clojure made really really simple
Clojure made really really simpleClojure made really really simple
Clojure made really really simple
 
From Lisp to Clojure/Incanter and RAn Introduction
From Lisp to Clojure/Incanter and RAn IntroductionFrom Lisp to Clojure/Incanter and RAn Introduction
From Lisp to Clojure/Incanter and RAn Introduction
 
From Java to Parellel Clojure - Clojure South 2019
From Java to Parellel Clojure - Clojure South 2019From Java to Parellel Clojure - Clojure South 2019
From Java to Parellel Clojure - Clojure South 2019
 

More from rik0

Pydiomatic
PydiomaticPydiomatic
Pydiomaticrik0
 
Pycrashcourse4.0 pdfjam
Pycrashcourse4.0 pdfjamPycrashcourse4.0 pdfjam
Pycrashcourse4.0 pdfjamrik0
 
Twcrashcourse
TwcrashcourseTwcrashcourse
Twcrashcourserik0
 
Pyimproved again
Pyimproved againPyimproved again
Pyimproved againrik0
 
Pycrashcourse3.1
Pycrashcourse3.1Pycrashcourse3.1
Pycrashcourse3.1rik0
 
Pycrashcourse3.0
Pycrashcourse3.0Pycrashcourse3.0
Pycrashcourse3.0rik0
 
Pycrashcourse2.0
Pycrashcourse2.0Pycrashcourse2.0
Pycrashcourse2.0rik0
 
Pycrashcourse
PycrashcoursePycrashcourse
Pycrashcourserik0
 

More from rik0 (8)

Pydiomatic
PydiomaticPydiomatic
Pydiomatic
 
Pycrashcourse4.0 pdfjam
Pycrashcourse4.0 pdfjamPycrashcourse4.0 pdfjam
Pycrashcourse4.0 pdfjam
 
Twcrashcourse
TwcrashcourseTwcrashcourse
Twcrashcourse
 
Pyimproved again
Pyimproved againPyimproved again
Pyimproved again
 
Pycrashcourse3.1
Pycrashcourse3.1Pycrashcourse3.1
Pycrashcourse3.1
 
Pycrashcourse3.0
Pycrashcourse3.0Pycrashcourse3.0
Pycrashcourse3.0
 
Pycrashcourse2.0
Pycrashcourse2.0Pycrashcourse2.0
Pycrashcourse2.0
 
Pycrashcourse
PycrashcoursePycrashcourse
Pycrashcourse
 

Recently uploaded

Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 

Recently uploaded (20)

Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 

Clojure Interoperability

  • 1. INTEROPERABILITY CLOJURE PYTHON Enrico Franchi
  • 2. 2 OUTLINE Why Clojure? Why Java? Clojure from 3000 m. Jython-Clojure interoperability Clojure-Jython interoperability ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  • 3. 3 GENERAL NOTES During 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 JVM LANGUAGES Jython Java ? JVM ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  • 5. 5 JVM LANGUAGES Jython Java Clojure JVM ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  • 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 JVM LANGUAGES Jython Implementation of Python in Java Jython calls Java ~ Clojure New Programming Languages built on the JVM Design choices in Clojure reflect design choices of the JVM Interoperability ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  • 8. 8 CLOJURE ~ Good Parts ~ Functional Programming Laziness Full Macros Multi-Methods Immutable types, STM & Concurrency Model ~ Bad Parts ~ “Java” ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  • 9. 9 ATOMIC TYPES Integers Floating Point Numbers Ratios (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 SEQUENCE TYPES Python Common Lisp Clojure Type Syntax Type Syntax Type Syntax Random access list [1, 2] vector #(1 2) vector [1 2] sequence Linked 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 collections In Clojure all collections are immutable; implement corresponding all the functions return a new collections – as usual, Java collections interfaces immutability allows easy data sharing – vector, list List set Set map Map ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  • 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 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 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 NAMESPACES & MODULES (ns example.namespace) (ns example.namespace (:require clojure.set)) Introduces a new namespace. With def (and defn, …) stuff is (ns example.namespace added 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 CALLING JAVA Java Clojure Jython import app.model.Person; (import [app.model Person]) from app.model import Person new Person() (new Person) Person() (Person.) person.getFullName() (. getFullName person) person.getFullName() (.getFullName person) Locale.JAPAN (. Locale JAPAN) Locale.JAPAN Locale/JAPAN Integer.valueOf(“42”) (. Integer valueOf "42") java.lang.Integer.valueOf('42') (Integer/valueOf “42”) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  • 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 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 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 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 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 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 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 CLOJURE RT from clojure.lang import RT, Compiler source = ''' (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 CLOJURE DECORATOR import pyclj @pyclj.clojure def 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 IMPLEMENTATION def 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 IMPLEMENTATION (2) def determine_clojure_namespace(fn):     try:         clj_namespace = fn.__module__     except AttributeError:         clj_namespace = 'user'     return clj_namespace def get_docs(clojure_fnc):     meta = clojure_fnc.meta()     return meta.get(Keyword.intern('doc')) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  • 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 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 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 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 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 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 CONCLUSION Thanks for Your Kind Attention https://github.com/rik0/PyCLJ_Examples https://github.com/rik0/pyclj ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  • 34. INTEROPERABILITY CLOJURE PYTHON Enrico Franchi
  • 35. 35 OUTLINE Why Clojure? Why Java? Clojure from 3000 m. Jython-Clojure interoperability Clojure-Jython interoperability ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  • 36. 36 GENERAL NOTES During 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 GENERAL NOTES During 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 JVM LANGUAGES Jython Java ? JVM ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  • 39. 39 JVM LANGUAGES Jython Java Clojure JVM ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  • 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 JVM LANGUAGES Jython Implementation of Python in Java Jython calls Java ~ Clojure New Programming Languages built on the JVM Design choices in Clojure reflect design choices of the JVM Interoperability ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  • 42. 42 CLOJURE ~ Good Parts ~ Functional Programming Laziness Full Macros Multi-Methods Immutable types, STM & Concurrency Model ~ Bad Parts ~ “Java” ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  • 43. 43 ATOMIC TYPES Integers Floating Point Numbers Ratios (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 SEQUENCE TYPES Python Common Lisp Clojure Type Syntax Type Syntax Type Syntax Random access list [1, 2] vector #(1 2) vector [1 2] sequence Linked 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 collections In Clojure all collections are immutable; implement corresponding all the functions return a new collections – as usual, Java collections interfaces immutability allows easy data sharing – vector, list List set Set map Map ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  • 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 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 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 NAMESPACES & MODULES (ns example.namespace) (ns example.namespace (:require clojure.set)) Introduces a new namespace. With def (and defn, …) stuff is (ns example.namespace added 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 CALLING JAVA Java Clojure Jython import app.model.Person; (import [app.model Person]) from app.model import Person new Person() (new Person) Person() (Person.) person.getFullName() (. getFullName person) person.getFullName() (.getFullName person) Locale.JAPAN (. Locale JAPAN) Locale.JAPAN Locale/JAPAN Integer.valueOf(“42”) (. Integer valueOf "42") java.lang.Integer.valueOf('42') (Integer/valueOf “42”) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  • 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 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 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 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 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 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 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 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 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 CLOJURE RT from clojure.lang import RT, Compiler source = ''' (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 CLOJURE DECORATOR import pyclj @pyclj.clojure def 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 IMPLEMENTATION def 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 IMPLEMENTATION (2) def determine_clojure_namespace(fn):     try:         clj_namespace = fn.__module__     except AttributeError:         clj_namespace = 'user'     return clj_namespace def get_docs(clojure_fnc):     meta = clojure_fnc.meta()     return meta.get(Keyword.intern('doc')) ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>
  • 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 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 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 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 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 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 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 CONCLUSION Thanks for Your Kind Attention https://github.com/rik0/PyCLJ_Examples https://github.com/rik0/pyclj ENRICO FRANCHI <EFRANCHI@CE.UNIPR.IT>