Note that there are some explanatory texts on larger screens.

plurals
  1. POCommon Lisp Backquote/Backtick: How to Use?
    text
    copied!<p>I am having trouble with Lisp's backquote read macro. Whenever I try to write a macro that seems to require the use of embedded backquotes (e.g., <code>``(w ,x ,,y)</code> from Paul Graham's <em>ANSI Common Lisp</em>, page 399), I cannot figure out how to write my code in a way that compiles. Typically, my code receives a whole chain of errors preceded with "Comma not inside a backquote." Can someone provide some guidelines for how I can write code that will evaluate properly?</p> <p>As an example, I currently need a macro which takes a form that describes a rule in the form of <code>'(function-name column-index value)</code> and generates a predicate lambda body to determine whether the element indexed by <code>column-index</code> for a particular row satisfies the rule. If I called this macro with the rule <code>'(&lt; 1 2)</code>, I would want a lambda body that looks like the following to be generated:</p> <pre><code>(lambda (row) (&lt; (svref row 1) 2)) </code></pre> <p>The best stab I can make at this is as follows:</p> <pre><code>(defmacro row-satisfies-rule (rule) (let ((x (gensym))) `(let ((,x ,rule)) (lambda (row) (`,(car ,x) (svref row `,(cadr ,x)) `,(caddr ,x)))))) </code></pre> <p>Upon evaluation, SBCL spews the following error report:</p> <pre><code>; in: ROW-SATISFIES-RULE '(&lt; 1 2) ; ((CAR #:G1121) (SVREF ROW (CADR #:G1121)) (CADDR #:G1121)) ; ; caught ERROR: ; illegal function call ; (LAMBDA (ROW) ((CAR #:G1121) (SVREF ROW (CADR #:G1121)) (CADDR #:G1121))) ; ==&gt; ; #'(LAMBDA (ROW) ((CAR #:G1121) (SVREF ROW (CADR #:G1121)) (CADDR #:G1121))) ; ; caught STYLE-WARNING: ; The variable ROW is defined but never used. ; (LET ((#:G1121 '(&lt; 1 2))) ; (LAMBDA (ROW) ((CAR #:G1121) (SVREF ROW (CADR #:G1121)) (CADDR #:G1121)))) ; ; caught STYLE-WARNING: ; The variable #:G1121 is defined but never used. ; ; compilation unit finished ; caught 1 ERROR condition ; caught 2 STYLE-WARNING conditions #&lt;FUNCTION (LAMBDA (ROW)) {2497F245}&gt; </code></pre> <p>How can I write macros to generate the code I need, and in particular, how do I implement <code>row-satisfies-rule</code>?</p> <hr> <p>Using the ideas from Ivijay and discipulus, I have modified the macro so that it compiles and works, even allowing forms to be passed as the arguments. It runs a bit differently from my originally planned macro since I determined that including <code>row</code> as an argument made for smoother code. However, it is ugly as sin. Does anyone know how to clean it up so it performs the same without the call to <code>eval</code>?</p> <pre><code>(defmacro row-satisfies-rule-p (row rule) (let ((x (gensym)) (y (gensym))) `(let ((,x ,row) (,y ,rule)) (destructuring-bind (a b c) ,y (eval `(,a (svref ,,x ,b) ,c)))))) </code></pre> <p>Also, an explanation of clean, Lispy ways to get macros to generate code to properly evaluate the arguments at runtime would be greatly appreciated.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload