Student
Student

Reputation: 719

Closure inside a Common Lisp Macro

In the following code how can i have the x and y variables to reflect the expressions given at macro call time?

(defmacro defrule (init-form &rest replication-patterns)
  (let (rule-table)
   `(destructuring-bind (p x y) ',init-form
       #'(lambda (w h) (list x y)))))

When expanding a call like:

(defrule (70 (* 1/2 w) (+ h 3)))

it returns:

(DESTRUCTURING-BIND (P X Y) '(70 (* 1/2 W) (+ H 3))
  #'(LAMBDA (W H) (LIST X Y)))

where the original expressions with W and H references are lost. I tried back-quoting the lambda function creation:

(defmacro defrule (init-form &rest replication-patterns)
  (let (rule-table)
    `(destructuring-bind (p x y) ',init-form
       `#'(lambda (w h) (list ,x ,y)))))

But a same call:

(defrule (70 (* 1/2 w) (+ h 3)))

expands to:

(DESTRUCTURING-BIND
    (P X Y)
    '(70 (* 1/2 W) (+ H 3))
  `#'(LAMBDA (W H) (LIST ,X ,Y)))

which returns a CONS:

#'(LAMBDA (W H) (LIST (* 1/2 W) (+ H 3)))

which can not be used by funcall and passed around like a function object easily. How can i return a function object with expressions i pass in as arguments for the x y part of the init-form with possible W H references being visible by the closure function?

Upvotes: 1

Views: 171

Answers (2)

Rainer Joswig
Rainer Joswig

Reputation: 139411

Looking at your code:

(defmacro defrule (init-form &rest replication-patterns)
  (let (rule-table)
   `(destructuring-bind (p x y) ',init-form
       #'(lambda (w h) (list x y)))))

You want a macro, which expands into code, which then at runtime takes code and returns a closure?

That's probably not a good idea.

Keep in mind: it's the macro, which should manipulate code at macro-expansion time. At runtime, the code should be fixed. See Barmar's explanation how to improve your code.

Upvotes: 4

Barmar
Barmar

Reputation: 782498

You're getting a cons because you have the backquotes nested.

You don't need backquote around destructuring-bind, because you're destructuring at macro expansion time, and you can do the destructuring directly in the macro lambda list.

(defmacro defrule ((p x y) &rest replication-patterns)
  (let (rule-table)
    `#'(lambda (w h) (list ,x ,y))))

Upvotes: 5

Related Questions