Lisp - Code Generation Using Macros



In LISP, macros is a powerful tool to extend language capability by writing a code which can generate code. Macros allows metaprogramming in LISP. In this chapter, we'll explore multiple examples of macros used in code generation.

Example - Create a Square Function using Macro

main.lisp

; define a macro accepting x and returns square of it
(defmacro my-square (x)
   `(* ,x ,x))
   
; (my-square 5) expands to (* 5 5)
(print (my-square 5))
(terpri)
; (my-square (+ 2 3)) expands to (* (+ 2 3)(+ 2 3))
(print (my-square (+ 2 3)))

Output

When you execute the code, it returns the following result −

25
25

Explanation

  • defmacro my-square (x) − macro my-square is defined using defmacro with an argument x

  • `(* ,x ,x) − a template is created using backquote and using comma, value of x will be inserted in the template

  • (my-square 5) − expression is expanded (* 5 5) and is evaluated as 25.

Example - Create a Loop using Macro

main.lisp

; define a macro to create a loop
(defmacro my-loop (var start end body)
  `(do ((,var ,start (+ ,var 1)))
       ((> ,var ,end))
     ,body))

; call loop to print 1 to 5
(my-loop i 1 5 (print i))

Output

When you execute the code, it returns the following result −

1
2
3
4
5

Explanation

  • defmacro my-loop − macro my-loop is defined using defmacro with an arguments to define a loop.

  • `(...) − a template is created using backquote and using do construct, a loop is run.

  • ,... − comma is used to insert values in the template.

Example - Create a Loop using Macro

main.lisp

; define a macro to create a loop
(defmacro my-loop (var start end body)
  `(do ((,var ,start (+ ,var 1)))
       ((> ,var ,end))
     ,body))

; call loop to print 1 to 5
(my-loop i 1 5 (print i))

Output

When you execute the code, it returns the following result −

1
2
3
4
5

Explanation

  • defmacro my-loop − macro my-loop is defined using defmacro with an arguments to define a loop.

  • (var start end body)− four parameters are passed, a loop variable, start value, end value and body of the loop.

  • `(...) − a template is created using backquote and using do construct, a loop is run.

  • ,... − comma is used to insert values in the template.

Example - Create a Function using Macro

main.lisp

; define a macro to define a function
(defmacro def-my-function (name params &body body)
  `(defun ,name ,params
     ,@body))

; define the function add-two-numbers using macro
(def-my-function add-two-numbers (x y)
  (+ x y))

; prints 7
(print (add-two-numbers 3 4))

Output

When you execute the code, it returns the following result −

7

Explanation

  • defmacro def-my-function − macro def-my-function is defined using defmacro with an arguments to define a function.

  • (name params &body body)− three parameters are passed, a function name, parameters to be pased and body of the function.

  • `(...) − a template is created using backquote and using do construct, a loop is run.

  • ,... − comma is used to insert values in the template.

  • ,@body − comma-at is used to insert body of the function.

  • def-my-function − macro is used to define a function by passing name of the function, parameters to be passed and a body.

Advertisements