Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>First of all, Lisp macros have "destructuring" argument lists. This is a nice feature that means instead of having an argument list <code>(rule)</code> and then taking it apart with <code>(car rule) (cadr rule) (caddr rule)</code>, you can simply make the argument list <code>((function-name column-index value))</code>. That way the macro expects a list of three elements as an argument, and each element of the list is then bound to the corresponding symbol in the arguemnt list. You can use this or not, but it's usually more convenient.</p> <p>Next, <code>`,</code> doesn't actually do anything, because the backquote tells Lisp not to evaluate the following expression and the comma tells it to evaluate it after all. I think you meant just <code>,(car x)</code>, which evaluates <code>(car x)</code>. This isn't a problem anyway if you use destructuring arguments.</p> <p>And since you're not introducing any new variables in the macro expansion, I don't think <code>(gensym)</code> is necessary in this case.</p> <p>So we can rewrite the macro like this:</p> <pre><code>(defmacro row-satisfies-rule ((function-name column-index value)) `(lambda (row) (,function-name (svref row ,column-index) ,value))) </code></pre> <p>Which expands just how you wanted:</p> <pre><code>(macroexpand-1 '(row-satisfies-rule (&lt; 1 2))) =&gt; (LAMBDA (ROW) (&lt; (SVREF ROW 1) 2)) </code></pre> <p>Hope this helps!</p> <hr> <p>If you need the argument to be evaluated to get the rule set, then here's a nice way to do it:</p> <pre><code>(defmacro row-satisfies-rule (rule) (destructuring-bind (function-name column-index value) (eval rule) `(lambda (row) (,function-name (svref row ,column-index) ,value)))) </code></pre> <p>Here's an example:</p> <pre><code>(let ((rules '((&lt; 1 2) (&gt; 3 4)))) (macroexpand-1 '(row-satisfies-rule (car rules)))) =&gt; (LAMBDA (ROW) (&lt; (SVREF ROW 1) 2)) </code></pre> <p>just like before.</p> <hr> <p>If you want to include <code>row</code> in the macro and have it give you your answer straightaway instead of making a function to do that, try this:</p> <pre><code>(defmacro row-satisfies-rule-p (row rule) (destructuring-bind (function-name column-index value) rule `(,function-name (svref ,row ,column-index) ,value))) </code></pre> <p>Or if you need to evaluate the <code>rule</code> argument (e.g. passing <code>'(&lt; 1 2)</code> or <code>(car rules)</code> instead of <code>(&lt; 1 2)</code>) then just use <code>(destructuring-bind (function-name column-index value) (eval rule)</code></p> <hr> <p>Actually, a function seems more appropriate than a macro for what you're trying to do. Simply</p> <pre><code>(defun row-satisfies-rule-p (row rule) (destructuring-bind (function-name column-index value) rule (funcall function-name (svref row column-index) value))) </code></pre> <p>works the same way as the macro and is much neater, without all the backquoting mess to worry about.</p> <p>In general, it's bad Lisp style to use macros for things that can be accomplished by functions.</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