SlideShare a Scribd company logo
Metaprogramming and Reflection
        Common Lisp

            Damien C ASSOU
            Hasso-Plattner-Institut Potsdam
             Software Architecture Group
              Prof. Dr. Robert Hirschfeld
      http://www.hpi.uni-potsdam.de/swa/
Metaprogramming and Reflection




 Syntax


   (function-name arg1 arg2 ... argn)


   > (+ 1 2)
   3




Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   2 / 56
Metaprogramming and Reflection




 Creating Lists
   > (cons 3 nil)
   (3)
   > (cons 2 (3))

   Impossible as 3 is not a function
   > (cons                  2 ’(3))
   (2 3)
   > (cons                  1 ’(2 3))
   (1 2 3)
   > (list                  1 2 3)
   (1 2 3)
   > ’(1 2                  3)
   (1 2 3)
Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   3 / 56
Metaprogramming and Reflection




 Studying Lists

   > (car ’(1 2 3))
   1
   > (cdr ’(1 2 3))
   (2 3)
   > (first ’(1 2 3))
   1
   > (last ’(1 2 3) 2)
   (2 3)
   > (last ’(1 2 3))
   (3)


Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   4 / 56
Metaprogramming and Reflection




 Creating Functions

   > (defun mult2 (x)
       "Multiplies x by 2"
       (* x 2))
   mult2

   defun is itself a function, it creates functions
   > (mult2 3)
   6


Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   5 / 56
Metaprogramming and Reflection




 Studying Functions


   > #’mult2
   #<FUNCTION mult2>
   > (describe #’mult2)
   (defun mult2 (x)
     "Multiplies x by 2"
     (* x 2))




Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   6 / 56
Metaprogramming and Reflection




 Calling Functions


   > (mult2 3)
   6
   > (funcall #’mult2 3)
   6
   > (defvar fmult2 #’mult2)
   fmult2
   > (funcall fmult2 3)
   6



Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   7 / 56
Metaprogramming and Reflection




 Summary

   In Lisp it is possible to:
        define new functions,
        retrieve a function by name,
        reference a function from a variable,
        call a function from a variable.


   This is very similar to pointer manipulation in C


Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   8 / 56
Metaprogramming and Reflection




 Function Pointer Manipulation in C

   int mult2 (int c) {
     return c * 2;
   }



   int main(void) {
     int (*fmult2) (int) = mult2;
     (*fmult2)(3);
   }

Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   9 / 56
Metaprogramming and Reflection




 Generating new Functions

   > (get-source ’mult2)
   (nil nil
        (defun mult2 (x)
          "Multiplies x by 2"
          (* x 2)))

   requires ibcl




Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   10 / 56
Metaprogramming and Reflection




 Generating new Functions


   > (defvar smult2
       (third (get-source ’mult2)))
   smult2
   > smult2
   (defun mult2 (x)
     "Multiplies x by 2"
     (* x 2))



Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   11 / 56
Metaprogramming and Reflection




 Generating new Functions

   > (first smult2)
   defun
   > (second smult2)
   mult2
   > (third smult2)
   (x)
   > (fourth smult2)
   "Multiplies x by 2"
   > (fifth smult2)
   (* x 2)


Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   12 / 56
Metaprogramming and Reflection




 Generating new Functions

   > (defvar smult10
        (copy-list smult2))
   smult10
   > (nsubstitute 10 2 (fifth smult10))
   nil
   > smult10
   (defun mult2 (x)
     "Multiplies x by 2"
     (* x 10))


Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   13 / 56
Metaprogramming and Reflection




 Generating new Functions

   > smult10
   (defun mult2 (x)
      "Multiplies x by 2"
     (* x 10))
   > (nsubstitute ’mult10 ’mult2
                  smult10)
   (defun mult10 (x)
      "Multiplies x by 2"
      (* x 10))


Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   14 / 56
Metaprogramming and Reflection




 Generating new Functions

   > smult10
   (defun mult10 (x)
     "Multiplies x by 2"
     (* x 10))
   > (setf (fourth smult10)
           (cl-ppcre:regex-replace "2"
             (fourth smult10) "10"))
   "Multiplies x by 10"



Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   15 / 56
Metaprogramming and Reflection




 Generating new Functions

   > smult10
   (defun mult10 (x)
      "Multiplies x by 10"
      (* x 10))
   > (eval smult10)
   mult10
   > (mult10 3)
   30



Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   16 / 56
Metaprogramming and Reflection




 Summary



             A function definition in Lisp is a list.
             This list can be studied like any list.
             New functions can be created from a list.




Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   17 / 56
Metaprogramming and Reflection




 Beyond Functions



   How would you implement while that executes its
   body as long as its condition stays true?
   > (while condition body)




Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   18 / 56
Metaprogramming and Reflection




 The While Construct
   > (setq i 10)
   > (while (/= i 0)
       (decf i)
       (format t "i is now: ~s~%" i))
   i is now: 9
   i is now: 8
   i is now: 7
   ...
   i is now: 2
   i is now: 1
   i is now: 0

Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   19 / 56
Metaprogramming and Reflection




 The While Construct: Using Loop

   > (while (/= i 0)
       (decf i)
       (format t "i is now: ~s~%" i))
   > (loop
       (if (not (/= i 0))
         (return)
         (progn
           (decf i)
           (format t "i = ~s~%" i))))


Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   20 / 56
Metaprogramming and Reflection




 The While Construct: Function
   > (defun while (test &rest body)
       (loop
         (if (not test)
             (return)
             (progn body))))
   > (while (/= i 0)
       (decf i)
       (format t "i is now: ~s~%" i))

   doesn’t work because parameters are evaluated
   immediately
   > (while t nil)
Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   21 / 56
Metaprogramming and Reflection




 Function Evaluation in C
   int f(int c){printf("fn");return c;}
   int g(int c){printf("gn");return c;}
   int h(int c){printf("hn");return c;}

   int main(void) {
     f(g(h(1)));
   }

   h
   g
   f
Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   22 / 56
Metaprogramming and Reflection




 The While Construct: Function
   > (defun while (test &rest body)
       (loop
         (if (not test)
             (return)
             (progn body))))
   > (while (/= i 0)
       (decf i)
       (format t "i is now: ~s~%" i))

   doesn’t work because parameters are evaluated
   immediately
   > (while t nil)
Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   23 / 56
Metaprogramming and Reflection




 The While Construct: Function
   > (while ’(/= i 0)
       ’(decf i)
       ’(format t "i is now: ~s~%" i))
   > (defun while (test &rest body)
       (loop
         (if (not (eval test))
             (return)
             (mapcar #’eval body))))

   works, but using while is less readable than intended

Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   24 / 56
Metaprogramming and Reflection




 Summary



             Arguments of functions are evaluated first.
             To prevent evaluation, use quote (or ’ ).
             Use eval to evaluate an expression.




Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   25 / 56
Metaprogramming and Reflection




 The While Construct: Macro
   > (loop
       (if (not (/= i 0))
         (return)
         (progn
           (decf i)
           (format t "i = ~s~%" i))))
   > (defmacro while (test &body body)
       (list ’loop
         (list ’if (list ’not test)
           (list ’return)
           (cons ’progn body))))
Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   26 / 56
Metaprogramming and Reflection




 The While Construct: Macro
   > (loop
       (if (not (/= i 0))
         (return)
         (progn
            (decf i)
            (format t "i = ~s~%" i))))
   > (defmacro while (test &body body)
       ‘(loop
           (if (not ,test)
             (return)
             (progn ,@body))))
Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   27 / 56
Metaprogramming and Reflection




 Macros



   Macros are programs that write programs
      they return lists representing Lisp code.
      they don’t evaluate their arguments.
      they are evaluated at compile time.




Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   28 / 56
Metaprogramming and Reflection




 Creating an OO language

   > (makeClass Speaker (name)
        (makeMethod speak (sentence)
          (format t
            "Listen all of you: ~s~%"
            sentence)))
   > (defvar alex (new ’Speaker "Alex"))
   > (call alex ’speak "Hello World!")
   Listen all of you: "Hello World!"
   > (getinstvar alex ’name)
   Alex


Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   29 / 56
Metaprogramming and Reflection




 Creating an OO language
   > (makeClass Speaker ()
       (makeMethod "..."))

   A class is composed of:
        a name,
        some instance variables,
        and some method definitions.

   > (defstruct cls
        name
        vars
        mths)
Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   30 / 56
Metaprogramming and Reflection




 Creating an OO language
   > (makeClass Speaker ()
       (makeMethod "..."))

   > (defmacro makeClass (name iVars
                          &body meths)
       ‘(push
          (make-cls
            :name ’,name
            :vars ’,iVars
            :mths
              ’,(mapcar #’eval meths))
          *classes*))
Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   31 / 56
Metaprogramming and Reflection




 Creating an OO language
   > (makeMethod speak (sentence)
       (format t "..." sentence))

   A method is composed of:
      a name,
      some parameters,
      a body

   > (defstruct mth
       name
       lmbd)
Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   32 / 56
Metaprogramming and Reflection




 Creating an OO language

   > (makeMethod speak (sentence)
       (format t "..." sentence))

   > (defmacro makeMethod (name
                  argNames &body body)
       ‘(make-mth
           :name ’,name
           :lmbd (lambda ,argNames
                           ,@body)))


Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   33 / 56
Metaprogramming and Reflection




 Creating an OO language

   > (new ’Speaker "Alex")

   An object is composed of:
       a reference to its class,
       some values for its instance variables

   > (defstruct obj
        cls
        values)


Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   34 / 56
Metaprogramming and Reflection




 Creating an OO language

   > (call alex ’speak "Hello World!")
   Listen all of you: "Hello World!"

   A call is a function with:
       the receiver object,
       a method name,
       and a list of parameters.

   (defun call (obj name &rest params)
      "...")

Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   35 / 56
Metaprogramming and Reflection




 Creating an OO language

   (defun call (obj name &rest params)
     (let* ((cls (obj-cls obj))
            (mth (getMethod cls name)))
         (apply (mth-lmbd mth)
                params)))

   (defun getMethod (cls name)
     (find name (cls-mths cls)
           :key #’mth-name))


Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   36 / 56
Metaprogramming and Reflection




 Creating an OO language
   > (getinstvar alex ’name)
   Alex

   Looking for an instance variable value from its name
   involves:
        getting the position of the name in the list of all
        instance variables of the class,
        taking the value at this position in the list of all
        values of the object.
     class:             varname1 varname2 . . .                               varnamen

     object:                value1                    value2            ...    valuen
Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present                    37 / 56
Metaprogramming and Reflection




 Creating an OO language

     class:             varname1 varname2 . . .                               varnamen

     object:                value1                    value2            ...    valuen
   (defun getInstVar (obj name)
     (let* ((cls (obj-cls obj))
            (vars (cls-vars cls))
            (pos (position name vars)))
       (nth pos (obj-values obj))))



Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present                    38 / 56
Metaprogramming and Reflection




 Handling this
   An object must be able to get its instance variables
   and call methods by using this .
   > (makeClass Speaker (name)
        (makeMethod getName ()
          (getInstVar ’this ’name)))
   > (call alex ’getname)
   Alex

   This requires the system to keep track of the current
   object.
   > (defparameter *cur-obj* nil)
Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   39 / 56
Metaprogramming and Reflection




 Handling this
   (defun getInstVar (obj name)
     (let* ((theObj
               (if (equal obj ’this)
                    *cur-obj*
                    obj))
            (cls (obj-cls theObj))
            (vars (cls-vars cls))
            (pos (position name vars)))
       (nth pos (obj-values theObj))))
   When is ∗cur−obj∗ updated? Before it is used!
   As this is only used when a method is executed, the
   method call needs to do the updating job.
Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   40 / 56
Metaprogramming and Reflection




 Handling this


   The method call needs to do the updating job:
   (defun call (obj name &rest params)
     (let* ((cls (obj-cls obj))
            (mth (getMethod cls name))
            (*cur-obj* obj))
         (apply (mth-lmbd mth)
                params)))


Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   41 / 56
Metaprogramming and Reflection




 Handling this

   We also want to pass this as first argument to call :
   (defun call (obj name &rest params)
     (let* ((theObj
               (if (equal obj ’this)
                    *cur-obj*
                    obj))
             (cls (obj-cls theObj))
           (mth (getMethod cls name)))
         (setf *cur-obj* theObj)
         (apply (mth-lmbd mth)
                params)))
Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   42 / 56
Metaprogramming and Reflection




 Creating an OO language


   Possible improvements:
       setting of instance variables
       inheritance
       constructors
       dedicated syntax




Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   43 / 56
Metaprogramming and Reflection




 Creating Domain-Specific Languages

   (makeClass Speaker (name)
     (makeMethod speak (s)
       (format t "I say: ~a" s))
     (makeMethod getName ()
       (call ’this ’speak "hi!")
       (getInstVar ’this ’name)))

   (makeMethod getName ()
       {c speak "hi!"}
       {i name})

Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   44 / 56
Metaprogramming and Reflection




 Creating Domain-Specific Languages
   ;; {c speak "hi!"} {i name}
   (set-macro-character #{
    (lambda (str)
      (let ((type (read-char str))
            (l (read-delimited-list
                             #} str)))
        (case type
         (#c ‘(call ’this
                     ’,(car l)
                     ,@(cdr l)))
         (#i ‘(getInstVar ’this
                            ’,(car l)))))))
Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   45 / 56
Metaprogramming and Reflection




 Summary



             Lisp has powerful functions to manipulate lists.
             Lisp source code is made of lists.
             As a result, meta-programming is made easy.




Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   46 / 56
Metaprogramming and Reflection




 Summary

   Macros
      can be used to create source code,
      don’t evaluate their arguments,
      are evaluated at compile time.


   Macros are programs that write programs.

   Macros can also be used to install a new syntax.

Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   47 / 56
Metaprogramming and Reflection




 A Glimpse at CLOS


   > (defclass circle ()
       (radius center))
   #<standard-class circle>
   > (make-instance ’circle)
   #<circle {B9CD249}>




Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   48 / 56
Metaprogramming and Reflection




 A Glimpse at CLOS

   > (defclass circle ()
       ((radius :accessor circle-radius)
        (center :accessor circle-center)))
   #<standard-class circle>
   > (setf c (make-instance ’circle))
   #<circle {ABC4629}>
   > (setf (circle-radius c) 6)
   6
   > (circle-radius c)
   6


Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   49 / 56
Metaprogramming and Reflection




 A Glimpse at CLOS
   > (defclass circle ()
       ((radius :accessor circle-radius
                :initarg :radius)
        (center :accessor circle-center
                :initarg :center)))
   #<standard-class circle>
   > (setf c (make-instance ’circle
                              :radius 6))
   #<circle {AC30D31}>
   > (circle-radius c)
   6

Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   50 / 56
Metaprogramming and Reflection




 A Glimpse at CLOS

   > (defmethod area ((c circle))
       (* pi (expt (circle-radius c) 2)))
   #<standard-method area (circle)>
   > (setf c (make-instance ’circle
                              :radius 6))
   #<circle {ACC00F1}>
   > (area c)
   113.09733552923255d0



Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   51 / 56
Metaprogramming and Reflection




 Auxiliary methods


   > (defmethod area ((c circle))
       (* pi (expt (circle-radius c) 2)))
   > (defmethod area :before ((c circle))
       (format t "I’m tired..."))
   > (area c)
   I’m tired...
   113.09733552923255d0



Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   52 / 56
Metaprogramming and Reflection




 Auxiliary methods

   (setf cache nil)
   (defun from-cache (c)
     (find (circle-radius c) cache
           :key #’car))
   (defun to-cache (c area)
     (push (cons (circle-radius c) area)
           cache)
     area)



Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   53 / 56
Metaprogramming and Reflection




 Auxiliary methods
   (defmethod area :around ((c circle))
    (let ((value (from-cache c)))
     (if value
      (progn
        (princ "Using the cache :-)")
        (cdr value))
      (progn
        (princ "So tired...")
        (to-cache c (call-next-method))))))
   > (area c)
   So tired...I’m tired...
   113.09733552923255d0
Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   54 / 56
Metaprogramming and Reflection




 Auxiliary methods


   > (area c)
   So tired...I’m tired...
   113.09733552923255d0
   > (area c)
   Using the cache :-)
   113.09733552923255d0




Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present   55 / 56
Metaprogramming and Reflection




 Acknowledgments

   Thanks to #lisp for all their help:

            akovalenko                                                  pjb
            antifuchs                                                   prxb
            H4ns                                                        ThomasH
            nikodemus

   These slides were created with a Common Lisp
   DSL: https://github.com/DamienCassou/DSLides

Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present             56 / 56

More Related Content

What's hot

CMake - Introduction and best practices
CMake - Introduction and best practicesCMake - Introduction and best practices
CMake - Introduction and best practices
Daniel Pfeifer
 
The Open-Closed Principle - the Original Version and the Contemporary Version
The Open-Closed Principle - the Original Version and the Contemporary VersionThe Open-Closed Principle - the Original Version and the Contemporary Version
The Open-Closed Principle - the Original Version and the Contemporary Version
Philip Schwarz
 
Bellman Ford's Algorithm
Bellman Ford's AlgorithmBellman Ford's Algorithm
Bellman Ford's Algorithm
Tanmay Baranwal
 
Dynamic programming, Branch and bound algorithm & Greedy algorithms
Dynamic programming, Branch and bound algorithm & Greedy algorithms Dynamic programming, Branch and bound algorithm & Greedy algorithms
Dynamic programming, Branch and bound algorithm & Greedy algorithms
SURBHI SAROHA
 
OptView2 - C++ on Sea 2022
OptView2 - C++ on Sea 2022OptView2 - C++ on Sea 2022
OptView2 - C++ on Sea 2022
Ofek Shilon
 
Introduction To Autumata Theory
 Introduction To Autumata Theory Introduction To Autumata Theory
Introduction To Autumata Theory
Abdul Rehman
 
Monad Laws Must be Checked
Monad Laws Must be CheckedMonad Laws Must be Checked
Monad Laws Must be Checked
Philip Schwarz
 
Normal forms cfg
Normal forms   cfgNormal forms   cfg
Normal forms cfg
Rajendran
 
Chomsky & Greibach Normal Forms
Chomsky & Greibach Normal FormsChomsky & Greibach Normal Forms
Chomsky & Greibach Normal Forms
Rajendran
 
Golang
GolangGolang
Syntactic analysis in NLP
Syntactic analysis in NLPSyntactic analysis in NLP
Syntactic analysis in NLP
kartikaVashisht
 
Lexical analysis
Lexical analysisLexical analysis
Lexical analysis
Richa Sharma
 
Cody Roux - Pure Type Systems - Boston Haskell Meetup
Cody Roux - Pure Type Systems - Boston Haskell MeetupCody Roux - Pure Type Systems - Boston Haskell Meetup
Cody Roux - Pure Type Systems - Boston Haskell Meetup
Greg Hale
 
Word Embedding to Document distances
Word Embedding to Document distancesWord Embedding to Document distances
Word Embedding to Document distances
Ganesh Borle
 
Context free grammars
Context free grammarsContext free grammars
Context free grammarsRonak Thakkar
 
How to write a TableGen backend
How to write a TableGen backendHow to write a TableGen backend
How to write a TableGen backend
Min-Yih Hsu
 
CFG to CNF
CFG to CNFCFG to CNF
CFG to CNF
Zain Ul Abiden
 
INTRODUCTION TO LISP
INTRODUCTION TO LISPINTRODUCTION TO LISP
INTRODUCTION TO LISP
Nilt1234
 

What's hot (20)

CMake - Introduction and best practices
CMake - Introduction and best practicesCMake - Introduction and best practices
CMake - Introduction and best practices
 
The Open-Closed Principle - the Original Version and the Contemporary Version
The Open-Closed Principle - the Original Version and the Contemporary VersionThe Open-Closed Principle - the Original Version and the Contemporary Version
The Open-Closed Principle - the Original Version and the Contemporary Version
 
Bellman Ford's Algorithm
Bellman Ford's AlgorithmBellman Ford's Algorithm
Bellman Ford's Algorithm
 
Dynamic programming, Branch and bound algorithm & Greedy algorithms
Dynamic programming, Branch and bound algorithm & Greedy algorithms Dynamic programming, Branch and bound algorithm & Greedy algorithms
Dynamic programming, Branch and bound algorithm & Greedy algorithms
 
OptView2 - C++ on Sea 2022
OptView2 - C++ on Sea 2022OptView2 - C++ on Sea 2022
OptView2 - C++ on Sea 2022
 
Introduction To Autumata Theory
 Introduction To Autumata Theory Introduction To Autumata Theory
Introduction To Autumata Theory
 
Monad Laws Must be Checked
Monad Laws Must be CheckedMonad Laws Must be Checked
Monad Laws Must be Checked
 
Normal forms cfg
Normal forms   cfgNormal forms   cfg
Normal forms cfg
 
Chomsky & Greibach Normal Forms
Chomsky & Greibach Normal FormsChomsky & Greibach Normal Forms
Chomsky & Greibach Normal Forms
 
Golang
GolangGolang
Golang
 
Syntactic analysis in NLP
Syntactic analysis in NLPSyntactic analysis in NLP
Syntactic analysis in NLP
 
Lexical analysis
Lexical analysisLexical analysis
Lexical analysis
 
Cody Roux - Pure Type Systems - Boston Haskell Meetup
Cody Roux - Pure Type Systems - Boston Haskell MeetupCody Roux - Pure Type Systems - Boston Haskell Meetup
Cody Roux - Pure Type Systems - Boston Haskell Meetup
 
Word Embedding to Document distances
Word Embedding to Document distancesWord Embedding to Document distances
Word Embedding to Document distances
 
Context free grammars
Context free grammarsContext free grammars
Context free grammars
 
Np complete
Np completeNp complete
Np complete
 
How to write a TableGen backend
How to write a TableGen backendHow to write a TableGen backend
How to write a TableGen backend
 
IBM Power10.pdf
IBM Power10.pdfIBM Power10.pdf
IBM Power10.pdf
 
CFG to CNF
CFG to CNFCFG to CNF
CFG to CNF
 
INTRODUCTION TO LISP
INTRODUCTION TO LISPINTRODUCTION TO LISP
INTRODUCTION TO LISP
 

Similar to Metaprogramming and Reflection in Common Lisp

ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015
Michiel Borkent
 
A Future for R: Parallel and Distributed Processing in R for Everyone
A Future for R: Parallel and Distributed Processing in R for EveryoneA Future for R: Parallel and Distributed Processing in R for Everyone
A Future for R: Parallel and Distributed Processing in R for Everyone
inside-BigData.com
 
Intro to Reactive Thinking and RxJava 2
Intro to Reactive Thinking and RxJava 2Intro to Reactive Thinking and RxJava 2
Intro to Reactive Thinking and RxJava 2
JollyRogers5
 
Hierarchical free monads and software design in fp
Hierarchical free monads and software design in fpHierarchical free monads and software design in fp
Hierarchical free monads and software design in fp
Alexander Granin
 
Implementation of 'go-like' language constructions in scala [english version]
Implementation of 'go-like' language constructions in scala [english version] Implementation of 'go-like' language constructions in scala [english version]
Implementation of 'go-like' language constructions in scala [english version]
Ruslan Shevchenko
 
Столпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай МозговойСтолпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай Мозговой
Sigma Software
 
golang_getting_started.pptx
golang_getting_started.pptxgolang_getting_started.pptx
golang_getting_started.pptx
Guy Komari
 
A gentle introduction to functional programming through music and clojure
A gentle introduction to functional programming through music and clojureA gentle introduction to functional programming through music and clojure
A gentle introduction to functional programming through music and clojure
Paul Lam
 
r,rstats,r language,r packages
r,rstats,r language,r packagesr,rstats,r language,r packages
r,rstats,r language,r packagesAjay Ohri
 
SCALA - Functional domain
SCALA -  Functional domainSCALA -  Functional domain
SCALA - Functional domain
Bartosz Kosarzycki
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with ClojureDmitry Buzdin
 
Spark training-in-bangalore
Spark training-in-bangaloreSpark training-in-bangalore
Spark training-in-bangalore
Kelly Technologies
 
Workshop presentation hands on r programming
Workshop presentation hands on r programmingWorkshop presentation hands on r programming
Workshop presentation hands on r programming
Nimrita Koul
 
CodeFest 2014. Axel Rauschmayer — JavaScript’s variables: scopes, environment...
CodeFest 2014. Axel Rauschmayer — JavaScript’s variables: scopes, environment...CodeFest 2014. Axel Rauschmayer — JavaScript’s variables: scopes, environment...
CodeFest 2014. Axel Rauschmayer — JavaScript’s variables: scopes, environment...CodeFest
 
RR & Docker @ MuensteR Meetup (Sep 2017)
RR & Docker @ MuensteR Meetup (Sep 2017)RR & Docker @ MuensteR Meetup (Sep 2017)
RR & Docker @ MuensteR Meetup (Sep 2017)
Daniel Nüst
 
Pune Clojure Course Outline
Pune Clojure Course OutlinePune Clojure Course Outline
Pune Clojure Course Outline
Baishampayan Ghose
 
Exploring Clojurescript
Exploring ClojurescriptExploring Clojurescript
Exploring Clojurescript
Luke Donnet
 
A Taste of Dotty
A Taste of DottyA Taste of Dotty
A Taste of Dotty
Hermann Hueck
 
New features in jdk8 iti
New features in jdk8 itiNew features in jdk8 iti
New features in jdk8 iti
Ahmed mar3y
 
Introduction to Scalding and Monoids
Introduction to Scalding and MonoidsIntroduction to Scalding and Monoids
Introduction to Scalding and Monoids
Hugo Gävert
 

Similar to Metaprogramming and Reflection in Common Lisp (20)

ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015
 
A Future for R: Parallel and Distributed Processing in R for Everyone
A Future for R: Parallel and Distributed Processing in R for EveryoneA Future for R: Parallel and Distributed Processing in R for Everyone
A Future for R: Parallel and Distributed Processing in R for Everyone
 
Intro to Reactive Thinking and RxJava 2
Intro to Reactive Thinking and RxJava 2Intro to Reactive Thinking and RxJava 2
Intro to Reactive Thinking and RxJava 2
 
Hierarchical free monads and software design in fp
Hierarchical free monads and software design in fpHierarchical free monads and software design in fp
Hierarchical free monads and software design in fp
 
Implementation of 'go-like' language constructions in scala [english version]
Implementation of 'go-like' language constructions in scala [english version] Implementation of 'go-like' language constructions in scala [english version]
Implementation of 'go-like' language constructions in scala [english version]
 
Столпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай МозговойСтолпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай Мозговой
 
golang_getting_started.pptx
golang_getting_started.pptxgolang_getting_started.pptx
golang_getting_started.pptx
 
A gentle introduction to functional programming through music and clojure
A gentle introduction to functional programming through music and clojureA gentle introduction to functional programming through music and clojure
A gentle introduction to functional programming through music and clojure
 
r,rstats,r language,r packages
r,rstats,r language,r packagesr,rstats,r language,r packages
r,rstats,r language,r packages
 
SCALA - Functional domain
SCALA -  Functional domainSCALA -  Functional domain
SCALA - Functional domain
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 
Spark training-in-bangalore
Spark training-in-bangaloreSpark training-in-bangalore
Spark training-in-bangalore
 
Workshop presentation hands on r programming
Workshop presentation hands on r programmingWorkshop presentation hands on r programming
Workshop presentation hands on r programming
 
CodeFest 2014. Axel Rauschmayer — JavaScript’s variables: scopes, environment...
CodeFest 2014. Axel Rauschmayer — JavaScript’s variables: scopes, environment...CodeFest 2014. Axel Rauschmayer — JavaScript’s variables: scopes, environment...
CodeFest 2014. Axel Rauschmayer — JavaScript’s variables: scopes, environment...
 
RR & Docker @ MuensteR Meetup (Sep 2017)
RR & Docker @ MuensteR Meetup (Sep 2017)RR & Docker @ MuensteR Meetup (Sep 2017)
RR & Docker @ MuensteR Meetup (Sep 2017)
 
Pune Clojure Course Outline
Pune Clojure Course OutlinePune Clojure Course Outline
Pune Clojure Course Outline
 
Exploring Clojurescript
Exploring ClojurescriptExploring Clojurescript
Exploring Clojurescript
 
A Taste of Dotty
A Taste of DottyA Taste of Dotty
A Taste of Dotty
 
New features in jdk8 iti
New features in jdk8 itiNew features in jdk8 iti
New features in jdk8 iti
 
Introduction to Scalding and Monoids
Introduction to Scalding and MonoidsIntroduction to Scalding and Monoids
Introduction to Scalding and Monoids
 

More from Damien Cassou

Pharo tutorial at ECOOP 2013
Pharo tutorial at ECOOP 2013Pharo tutorial at ECOOP 2013
Pharo tutorial at ECOOP 2013
Damien Cassou
 
Leveraging Software Architectures to Guide and Verify the Development of Sen...
Leveraging Software Architectures to Guide and Verify the Development of Sen...Leveraging Software Architectures to Guide and Verify the Development of Sen...
Leveraging Software Architectures to Guide and Verify the Development of Sen...
Damien Cassou
 
Architecture-Driven Programming for Sense/Compute/Control Applications
Architecture-Driven Programming for Sense/Compute/Control ApplicationsArchitecture-Driven Programming for Sense/Compute/Control Applications
Architecture-Driven Programming for Sense/Compute/Control Applications
Damien Cassou
 
A Generative Programming Approach to Developing Pervasive Computing Systems
A Generative Programming Approach to Developing Pervasive Computing SystemsA Generative Programming Approach to Developing Pervasive Computing Systems
A Generative Programming Approach to Developing Pervasive Computing Systems
Damien Cassou
 
Smalltalk
SmalltalkSmalltalk
Smalltalk
Damien Cassou
 

More from Damien Cassou (6)

Pharo tutorial at ECOOP 2013
Pharo tutorial at ECOOP 2013Pharo tutorial at ECOOP 2013
Pharo tutorial at ECOOP 2013
 
Leveraging Software Architectures to Guide and Verify the Development of Sen...
Leveraging Software Architectures to Guide and Verify the Development of Sen...Leveraging Software Architectures to Guide and Verify the Development of Sen...
Leveraging Software Architectures to Guide and Verify the Development of Sen...
 
PhD thesis defense
PhD thesis defensePhD thesis defense
PhD thesis defense
 
Architecture-Driven Programming for Sense/Compute/Control Applications
Architecture-Driven Programming for Sense/Compute/Control ApplicationsArchitecture-Driven Programming for Sense/Compute/Control Applications
Architecture-Driven Programming for Sense/Compute/Control Applications
 
A Generative Programming Approach to Developing Pervasive Computing Systems
A Generative Programming Approach to Developing Pervasive Computing SystemsA Generative Programming Approach to Developing Pervasive Computing Systems
A Generative Programming Approach to Developing Pervasive Computing Systems
 
Smalltalk
SmalltalkSmalltalk
Smalltalk
 

Recently uploaded

2015pmkemenhub163.pdf 2015pmkemenhub163.pdf
2015pmkemenhub163.pdf 2015pmkemenhub163.pdf2015pmkemenhub163.pdf 2015pmkemenhub163.pdf
2015pmkemenhub163.pdf 2015pmkemenhub163.pdf
CIkumparan
 
EED - The Container Port PERFORMANCE INDEX 2023
EED - The Container Port PERFORMANCE INDEX 2023EED - The Container Port PERFORMANCE INDEX 2023
EED - The Container Port PERFORMANCE INDEX 2023
El Estrecho Digital
 
What Ukraine Has Lost During Russia’s Invasion
What Ukraine Has Lost During Russia’s InvasionWhat Ukraine Has Lost During Russia’s Invasion
What Ukraine Has Lost During Russia’s Invasion
LUMINATIVE MEDIA/PROJECT COUNSEL MEDIA GROUP
 
Hindustan Insider 2nd edition release now
Hindustan Insider 2nd edition release nowHindustan Insider 2nd edition release now
Hindustan Insider 2nd edition release now
hindustaninsider22
 
04062024_First India Newspaper Jaipur.pdf
04062024_First India Newspaper Jaipur.pdf04062024_First India Newspaper Jaipur.pdf
04062024_First India Newspaper Jaipur.pdf
FIRST INDIA
 
Gabriel Whitley's Motion Summary Judgment
Gabriel Whitley's Motion Summary JudgmentGabriel Whitley's Motion Summary Judgment
Gabriel Whitley's Motion Summary Judgment
Abdul-Hakim Shabazz
 
Codes n Conventionss copy (1).paaaaaaptx
Codes n Conventionss copy (1).paaaaaaptxCodes n Conventionss copy (1).paaaaaaptx
Codes n Conventionss copy (1).paaaaaaptx
ZackSpencer3
 
Resolutions-Key-Interventions-28-May-2024.pdf
Resolutions-Key-Interventions-28-May-2024.pdfResolutions-Key-Interventions-28-May-2024.pdf
Resolutions-Key-Interventions-28-May-2024.pdf
bhavenpr
 
Preview of Court Document for Iseyin community
Preview of Court Document for Iseyin communityPreview of Court Document for Iseyin community
Preview of Court Document for Iseyin community
contact193699
 
Hogan Comes Home: an MIA WWII crewman is returned
Hogan Comes Home: an MIA WWII crewman is returnedHogan Comes Home: an MIA WWII crewman is returned
Hogan Comes Home: an MIA WWII crewman is returned
rbakerj2
 
01062024_First India Newspaper Jaipur.pdf
01062024_First India Newspaper Jaipur.pdf01062024_First India Newspaper Jaipur.pdf
01062024_First India Newspaper Jaipur.pdf
FIRST INDIA
 
03062024_First India Newspaper Jaipur.pdf
03062024_First India Newspaper Jaipur.pdf03062024_First India Newspaper Jaipur.pdf
03062024_First India Newspaper Jaipur.pdf
FIRST INDIA
 
Letter-from-ECI-to-MeiTY-21st-march-2024.pdf
Letter-from-ECI-to-MeiTY-21st-march-2024.pdfLetter-from-ECI-to-MeiTY-21st-march-2024.pdf
Letter-from-ECI-to-MeiTY-21st-march-2024.pdf
bhavenpr
 

Recently uploaded (13)

2015pmkemenhub163.pdf 2015pmkemenhub163.pdf
2015pmkemenhub163.pdf 2015pmkemenhub163.pdf2015pmkemenhub163.pdf 2015pmkemenhub163.pdf
2015pmkemenhub163.pdf 2015pmkemenhub163.pdf
 
EED - The Container Port PERFORMANCE INDEX 2023
EED - The Container Port PERFORMANCE INDEX 2023EED - The Container Port PERFORMANCE INDEX 2023
EED - The Container Port PERFORMANCE INDEX 2023
 
What Ukraine Has Lost During Russia’s Invasion
What Ukraine Has Lost During Russia’s InvasionWhat Ukraine Has Lost During Russia’s Invasion
What Ukraine Has Lost During Russia’s Invasion
 
Hindustan Insider 2nd edition release now
Hindustan Insider 2nd edition release nowHindustan Insider 2nd edition release now
Hindustan Insider 2nd edition release now
 
04062024_First India Newspaper Jaipur.pdf
04062024_First India Newspaper Jaipur.pdf04062024_First India Newspaper Jaipur.pdf
04062024_First India Newspaper Jaipur.pdf
 
Gabriel Whitley's Motion Summary Judgment
Gabriel Whitley's Motion Summary JudgmentGabriel Whitley's Motion Summary Judgment
Gabriel Whitley's Motion Summary Judgment
 
Codes n Conventionss copy (1).paaaaaaptx
Codes n Conventionss copy (1).paaaaaaptxCodes n Conventionss copy (1).paaaaaaptx
Codes n Conventionss copy (1).paaaaaaptx
 
Resolutions-Key-Interventions-28-May-2024.pdf
Resolutions-Key-Interventions-28-May-2024.pdfResolutions-Key-Interventions-28-May-2024.pdf
Resolutions-Key-Interventions-28-May-2024.pdf
 
Preview of Court Document for Iseyin community
Preview of Court Document for Iseyin communityPreview of Court Document for Iseyin community
Preview of Court Document for Iseyin community
 
Hogan Comes Home: an MIA WWII crewman is returned
Hogan Comes Home: an MIA WWII crewman is returnedHogan Comes Home: an MIA WWII crewman is returned
Hogan Comes Home: an MIA WWII crewman is returned
 
01062024_First India Newspaper Jaipur.pdf
01062024_First India Newspaper Jaipur.pdf01062024_First India Newspaper Jaipur.pdf
01062024_First India Newspaper Jaipur.pdf
 
03062024_First India Newspaper Jaipur.pdf
03062024_First India Newspaper Jaipur.pdf03062024_First India Newspaper Jaipur.pdf
03062024_First India Newspaper Jaipur.pdf
 
Letter-from-ECI-to-MeiTY-21st-march-2024.pdf
Letter-from-ECI-to-MeiTY-21st-march-2024.pdfLetter-from-ECI-to-MeiTY-21st-march-2024.pdf
Letter-from-ECI-to-MeiTY-21st-march-2024.pdf
 

Metaprogramming and Reflection in Common Lisp

  • 1. Metaprogramming and Reflection Common Lisp Damien C ASSOU Hasso-Plattner-Institut Potsdam Software Architecture Group Prof. Dr. Robert Hirschfeld http://www.hpi.uni-potsdam.de/swa/
  • 2. Metaprogramming and Reflection Syntax (function-name arg1 arg2 ... argn) > (+ 1 2) 3 Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 2 / 56
  • 3. Metaprogramming and Reflection Creating Lists > (cons 3 nil) (3) > (cons 2 (3)) Impossible as 3 is not a function > (cons 2 ’(3)) (2 3) > (cons 1 ’(2 3)) (1 2 3) > (list 1 2 3) (1 2 3) > ’(1 2 3) (1 2 3) Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 3 / 56
  • 4. Metaprogramming and Reflection Studying Lists > (car ’(1 2 3)) 1 > (cdr ’(1 2 3)) (2 3) > (first ’(1 2 3)) 1 > (last ’(1 2 3) 2) (2 3) > (last ’(1 2 3)) (3) Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 4 / 56
  • 5. Metaprogramming and Reflection Creating Functions > (defun mult2 (x) "Multiplies x by 2" (* x 2)) mult2 defun is itself a function, it creates functions > (mult2 3) 6 Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 5 / 56
  • 6. Metaprogramming and Reflection Studying Functions > #’mult2 #<FUNCTION mult2> > (describe #’mult2) (defun mult2 (x) "Multiplies x by 2" (* x 2)) Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 6 / 56
  • 7. Metaprogramming and Reflection Calling Functions > (mult2 3) 6 > (funcall #’mult2 3) 6 > (defvar fmult2 #’mult2) fmult2 > (funcall fmult2 3) 6 Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 7 / 56
  • 8. Metaprogramming and Reflection Summary In Lisp it is possible to: define new functions, retrieve a function by name, reference a function from a variable, call a function from a variable. This is very similar to pointer manipulation in C Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 8 / 56
  • 9. Metaprogramming and Reflection Function Pointer Manipulation in C int mult2 (int c) { return c * 2; } int main(void) { int (*fmult2) (int) = mult2; (*fmult2)(3); } Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 9 / 56
  • 10. Metaprogramming and Reflection Generating new Functions > (get-source ’mult2) (nil nil (defun mult2 (x) "Multiplies x by 2" (* x 2))) requires ibcl Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 10 / 56
  • 11. Metaprogramming and Reflection Generating new Functions > (defvar smult2 (third (get-source ’mult2))) smult2 > smult2 (defun mult2 (x) "Multiplies x by 2" (* x 2)) Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 11 / 56
  • 12. Metaprogramming and Reflection Generating new Functions > (first smult2) defun > (second smult2) mult2 > (third smult2) (x) > (fourth smult2) "Multiplies x by 2" > (fifth smult2) (* x 2) Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 12 / 56
  • 13. Metaprogramming and Reflection Generating new Functions > (defvar smult10 (copy-list smult2)) smult10 > (nsubstitute 10 2 (fifth smult10)) nil > smult10 (defun mult2 (x) "Multiplies x by 2" (* x 10)) Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 13 / 56
  • 14. Metaprogramming and Reflection Generating new Functions > smult10 (defun mult2 (x) "Multiplies x by 2" (* x 10)) > (nsubstitute ’mult10 ’mult2 smult10) (defun mult10 (x) "Multiplies x by 2" (* x 10)) Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 14 / 56
  • 15. Metaprogramming and Reflection Generating new Functions > smult10 (defun mult10 (x) "Multiplies x by 2" (* x 10)) > (setf (fourth smult10) (cl-ppcre:regex-replace "2" (fourth smult10) "10")) "Multiplies x by 10" Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 15 / 56
  • 16. Metaprogramming and Reflection Generating new Functions > smult10 (defun mult10 (x) "Multiplies x by 10" (* x 10)) > (eval smult10) mult10 > (mult10 3) 30 Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 16 / 56
  • 17. Metaprogramming and Reflection Summary A function definition in Lisp is a list. This list can be studied like any list. New functions can be created from a list. Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 17 / 56
  • 18. Metaprogramming and Reflection Beyond Functions How would you implement while that executes its body as long as its condition stays true? > (while condition body) Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 18 / 56
  • 19. Metaprogramming and Reflection The While Construct > (setq i 10) > (while (/= i 0) (decf i) (format t "i is now: ~s~%" i)) i is now: 9 i is now: 8 i is now: 7 ... i is now: 2 i is now: 1 i is now: 0 Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 19 / 56
  • 20. Metaprogramming and Reflection The While Construct: Using Loop > (while (/= i 0) (decf i) (format t "i is now: ~s~%" i)) > (loop (if (not (/= i 0)) (return) (progn (decf i) (format t "i = ~s~%" i)))) Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 20 / 56
  • 21. Metaprogramming and Reflection The While Construct: Function > (defun while (test &rest body) (loop (if (not test) (return) (progn body)))) > (while (/= i 0) (decf i) (format t "i is now: ~s~%" i)) doesn’t work because parameters are evaluated immediately > (while t nil) Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 21 / 56
  • 22. Metaprogramming and Reflection Function Evaluation in C int f(int c){printf("fn");return c;} int g(int c){printf("gn");return c;} int h(int c){printf("hn");return c;} int main(void) { f(g(h(1))); } h g f Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 22 / 56
  • 23. Metaprogramming and Reflection The While Construct: Function > (defun while (test &rest body) (loop (if (not test) (return) (progn body)))) > (while (/= i 0) (decf i) (format t "i is now: ~s~%" i)) doesn’t work because parameters are evaluated immediately > (while t nil) Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 23 / 56
  • 24. Metaprogramming and Reflection The While Construct: Function > (while ’(/= i 0) ’(decf i) ’(format t "i is now: ~s~%" i)) > (defun while (test &rest body) (loop (if (not (eval test)) (return) (mapcar #’eval body)))) works, but using while is less readable than intended Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 24 / 56
  • 25. Metaprogramming and Reflection Summary Arguments of functions are evaluated first. To prevent evaluation, use quote (or ’ ). Use eval to evaluate an expression. Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 25 / 56
  • 26. Metaprogramming and Reflection The While Construct: Macro > (loop (if (not (/= i 0)) (return) (progn (decf i) (format t "i = ~s~%" i)))) > (defmacro while (test &body body) (list ’loop (list ’if (list ’not test) (list ’return) (cons ’progn body)))) Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 26 / 56
  • 27. Metaprogramming and Reflection The While Construct: Macro > (loop (if (not (/= i 0)) (return) (progn (decf i) (format t "i = ~s~%" i)))) > (defmacro while (test &body body) ‘(loop (if (not ,test) (return) (progn ,@body)))) Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 27 / 56
  • 28. Metaprogramming and Reflection Macros Macros are programs that write programs they return lists representing Lisp code. they don’t evaluate their arguments. they are evaluated at compile time. Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 28 / 56
  • 29. Metaprogramming and Reflection Creating an OO language > (makeClass Speaker (name) (makeMethod speak (sentence) (format t "Listen all of you: ~s~%" sentence))) > (defvar alex (new ’Speaker "Alex")) > (call alex ’speak "Hello World!") Listen all of you: "Hello World!" > (getinstvar alex ’name) Alex Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 29 / 56
  • 30. Metaprogramming and Reflection Creating an OO language > (makeClass Speaker () (makeMethod "...")) A class is composed of: a name, some instance variables, and some method definitions. > (defstruct cls name vars mths) Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 30 / 56
  • 31. Metaprogramming and Reflection Creating an OO language > (makeClass Speaker () (makeMethod "...")) > (defmacro makeClass (name iVars &body meths) ‘(push (make-cls :name ’,name :vars ’,iVars :mths ’,(mapcar #’eval meths)) *classes*)) Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 31 / 56
  • 32. Metaprogramming and Reflection Creating an OO language > (makeMethod speak (sentence) (format t "..." sentence)) A method is composed of: a name, some parameters, a body > (defstruct mth name lmbd) Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 32 / 56
  • 33. Metaprogramming and Reflection Creating an OO language > (makeMethod speak (sentence) (format t "..." sentence)) > (defmacro makeMethod (name argNames &body body) ‘(make-mth :name ’,name :lmbd (lambda ,argNames ,@body))) Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 33 / 56
  • 34. Metaprogramming and Reflection Creating an OO language > (new ’Speaker "Alex") An object is composed of: a reference to its class, some values for its instance variables > (defstruct obj cls values) Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 34 / 56
  • 35. Metaprogramming and Reflection Creating an OO language > (call alex ’speak "Hello World!") Listen all of you: "Hello World!" A call is a function with: the receiver object, a method name, and a list of parameters. (defun call (obj name &rest params) "...") Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 35 / 56
  • 36. Metaprogramming and Reflection Creating an OO language (defun call (obj name &rest params) (let* ((cls (obj-cls obj)) (mth (getMethod cls name))) (apply (mth-lmbd mth) params))) (defun getMethod (cls name) (find name (cls-mths cls) :key #’mth-name)) Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 36 / 56
  • 37. Metaprogramming and Reflection Creating an OO language > (getinstvar alex ’name) Alex Looking for an instance variable value from its name involves: getting the position of the name in the list of all instance variables of the class, taking the value at this position in the list of all values of the object. class: varname1 varname2 . . . varnamen object: value1 value2 ... valuen Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 37 / 56
  • 38. Metaprogramming and Reflection Creating an OO language class: varname1 varname2 . . . varnamen object: value1 value2 ... valuen (defun getInstVar (obj name) (let* ((cls (obj-cls obj)) (vars (cls-vars cls)) (pos (position name vars))) (nth pos (obj-values obj)))) Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 38 / 56
  • 39. Metaprogramming and Reflection Handling this An object must be able to get its instance variables and call methods by using this . > (makeClass Speaker (name) (makeMethod getName () (getInstVar ’this ’name))) > (call alex ’getname) Alex This requires the system to keep track of the current object. > (defparameter *cur-obj* nil) Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 39 / 56
  • 40. Metaprogramming and Reflection Handling this (defun getInstVar (obj name) (let* ((theObj (if (equal obj ’this) *cur-obj* obj)) (cls (obj-cls theObj)) (vars (cls-vars cls)) (pos (position name vars))) (nth pos (obj-values theObj)))) When is ∗cur−obj∗ updated? Before it is used! As this is only used when a method is executed, the method call needs to do the updating job. Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 40 / 56
  • 41. Metaprogramming and Reflection Handling this The method call needs to do the updating job: (defun call (obj name &rest params) (let* ((cls (obj-cls obj)) (mth (getMethod cls name)) (*cur-obj* obj)) (apply (mth-lmbd mth) params))) Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 41 / 56
  • 42. Metaprogramming and Reflection Handling this We also want to pass this as first argument to call : (defun call (obj name &rest params) (let* ((theObj (if (equal obj ’this) *cur-obj* obj)) (cls (obj-cls theObj)) (mth (getMethod cls name))) (setf *cur-obj* theObj) (apply (mth-lmbd mth) params))) Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 42 / 56
  • 43. Metaprogramming and Reflection Creating an OO language Possible improvements: setting of instance variables inheritance constructors dedicated syntax Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 43 / 56
  • 44. Metaprogramming and Reflection Creating Domain-Specific Languages (makeClass Speaker (name) (makeMethod speak (s) (format t "I say: ~a" s)) (makeMethod getName () (call ’this ’speak "hi!") (getInstVar ’this ’name))) (makeMethod getName () {c speak "hi!"} {i name}) Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 44 / 56
  • 45. Metaprogramming and Reflection Creating Domain-Specific Languages ;; {c speak "hi!"} {i name} (set-macro-character #{ (lambda (str) (let ((type (read-char str)) (l (read-delimited-list #} str))) (case type (#c ‘(call ’this ’,(car l) ,@(cdr l))) (#i ‘(getInstVar ’this ’,(car l))))))) Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 45 / 56
  • 46. Metaprogramming and Reflection Summary Lisp has powerful functions to manipulate lists. Lisp source code is made of lists. As a result, meta-programming is made easy. Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 46 / 56
  • 47. Metaprogramming and Reflection Summary Macros can be used to create source code, don’t evaluate their arguments, are evaluated at compile time. Macros are programs that write programs. Macros can also be used to install a new syntax. Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 47 / 56
  • 48. Metaprogramming and Reflection A Glimpse at CLOS > (defclass circle () (radius center)) #<standard-class circle> > (make-instance ’circle) #<circle {B9CD249}> Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 48 / 56
  • 49. Metaprogramming and Reflection A Glimpse at CLOS > (defclass circle () ((radius :accessor circle-radius) (center :accessor circle-center))) #<standard-class circle> > (setf c (make-instance ’circle)) #<circle {ABC4629}> > (setf (circle-radius c) 6) 6 > (circle-radius c) 6 Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 49 / 56
  • 50. Metaprogramming and Reflection A Glimpse at CLOS > (defclass circle () ((radius :accessor circle-radius :initarg :radius) (center :accessor circle-center :initarg :center))) #<standard-class circle> > (setf c (make-instance ’circle :radius 6)) #<circle {AC30D31}> > (circle-radius c) 6 Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 50 / 56
  • 51. Metaprogramming and Reflection A Glimpse at CLOS > (defmethod area ((c circle)) (* pi (expt (circle-radius c) 2))) #<standard-method area (circle)> > (setf c (make-instance ’circle :radius 6)) #<circle {ACC00F1}> > (area c) 113.09733552923255d0 Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 51 / 56
  • 52. Metaprogramming and Reflection Auxiliary methods > (defmethod area ((c circle)) (* pi (expt (circle-radius c) 2))) > (defmethod area :before ((c circle)) (format t "I’m tired...")) > (area c) I’m tired... 113.09733552923255d0 Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 52 / 56
  • 53. Metaprogramming and Reflection Auxiliary methods (setf cache nil) (defun from-cache (c) (find (circle-radius c) cache :key #’car)) (defun to-cache (c area) (push (cons (circle-radius c) area) cache) area) Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 53 / 56
  • 54. Metaprogramming and Reflection Auxiliary methods (defmethod area :around ((c circle)) (let ((value (from-cache c))) (if value (progn (princ "Using the cache :-)") (cdr value)) (progn (princ "So tired...") (to-cache c (call-next-method)))))) > (area c) So tired...I’m tired... 113.09733552923255d0 Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 54 / 56
  • 55. Metaprogramming and Reflection Auxiliary methods > (area c) So tired...I’m tired... 113.09733552923255d0 > (area c) Using the cache :-) 113.09733552923255d0 Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 55 / 56
  • 56. Metaprogramming and Reflection Acknowledgments Thanks to #lisp for all their help: akovalenko pjb antifuchs prxb H4ns ThomasH nikodemus These slides were created with a Common Lisp DSL: https://github.com/DamienCassou/DSLides Software Architecture Group (www.hpi.uni-potsdam.de/swa) 2006–present 56 / 56