Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lisp: Pass &rest parameters to a macro

I'm trying to build a function to access records in a database as such:

(select :title "milk" :rating 7)

However, it's just returning all of the records in the database. I believe this is because I'm passing &rest arguments to a macro and it's interpreting the parameter name "fields" literally. I've tried removing &rest from my macro, but then I get an error about not passing a list. I've tried calling (list fields) in various places to no avail (in the macro, in the function that calls the macro, in the function that the macro calls).

The following code works as expected:

(select-custom (where :title "milk" :rating 7))

And returns only the records which match the arguments.

source code:

(defun select (&rest fields)
  (select-custom (where fields)))

(defun select-custom (selector-function)
  (remove-if-not selector-function *db*))

(defmacro where (&rest fields)
  `#'(lambda (cd) (and ,@(make-comparison-list fields))))    

(defun make-comparison-list (fields)
  (loop while fields
        collecting (make-comparison-exp (pop fields) (pop fields))))

(defun make-comparison-exp (field value)
  `(equal (getf cd ,field) ,value))
like image 887
user1376243 Avatar asked Jan 06 '23 23:01

user1376243


1 Answers

You could just make select a macro instead

(defmacro select (&rest fields)
  `(select-custom (where ,@fields)))

You can check that

(macroexpand-1 '(select :title "milk" :rating 7))

returns

(SELECT-CUSTOM (WHERE :TITLE "milk" :RATING 7))
like image 83
6502 Avatar answered Jan 15 '23 02:01

6502