Starting out with Lisp - stuck on a macro

Discussion of Common Lisp
Post Reply
Plu
Posts: 3
Joined: Mon Jul 21, 2014 12:12 pm

Starting out with Lisp - stuck on a macro

Post by Plu » Mon Jul 21, 2014 12:20 pm

I was following through Practical Common LISP and then at some point I tried to play around a bit, but I seem to be getting stuck. I've been playing around for a bit with the chapter "Making a database" and was trying to convert the "update" mechanism to use a snazzy macro the way the book teaches you to do with "where".

I think I got most of it to work, but now I'm really confused about the last step, because it's suddenly trying to call keyword arguments as a function (which doesn't work)

This is a piece of the book which explains the workings of the "where", if that's helpful: http://www.gigamonkeys.com/book/practic ... abase.html

And this is what I have now:

Code: Select all

(defun make-modify-expr (field value)
  `(setf (getf row ,field) ,value))

(defun make-modify-list (fields)
  (loop while fields
       collecting (make-modify-expr (pop fields) (pop fields))))

(defmacro update-row (selector-fn &rest clauses)
  `#'(lambda (row) (when (funcall ,selector-fn row)
       (and ,@(make-modify-list clauses)))))

(defmacro updatem (selector-fn &rest clauses)
  `(mapcar
    (update-row ,selector-fn ,clauses)
    *db* ))
And now I'm trying to call it like this;

Code: Select all

(updatem (where :rating 6) :rating 7)
But then I get the message:

Code: Select all

;Compiler warnings :
;   In an anonymous lambda form: Undefined function :RATING
My basic idea was that update-row would pop out a lambda function that would (through make-modify-list) build a function that would setf whichever fields you'd pass to updatem. But instead it seems to be trying to call the keyworded field names themselves as functions somewhere? I just can't really figure out where and I'm not seeing a backtrace anymore (not that I could really read those anyway).

I'm hoping anyone could explain to me what is going wrong here. This LISP stuff sounds amazing, but I'm having some trouble trying to understand what is actually happening in some of these functions.

pjstirling
Posts: 166
Joined: Sun Nov 28, 2010 4:21 pm

Re: Starting out with Lisp - stuck on a macro

Post by pjstirling » Tue Jul 22, 2014 5:39 am

If you are using SLIME in emacs, you can put the cursor on the opening paren, and use "C-c Return" to macroexpand a macro, here's what you get for the call you provided:

Code: Select all

(MAPCAR (UPDATE-ROW (WHERE :RATING 6) (:RATING 7)) *DB*)
So, yes, you are trying to call a function named by a keyword.

Plu
Posts: 3
Joined: Mon Jul 21, 2014 12:12 pm

Re: Starting out with Lisp - stuck on a macro

Post by Plu » Tue Jul 22, 2014 5:55 am

I'll have to try that SLIME thing at home, didn't know that. Sounds very useful.

Without access to my lisp enviroment (not behind my own pc right now), would I be correct in saying that I forgot a splat operator and that updatem should look more like this?

Code: Select all

(defmacro updatem (selector-fn &rest clauses)
  `(mapcar
    (update-row ,selector-fn ,@clauses)
    *db* ))
Because all the extra clauses are put into a list and thus passed onto update-row as a single list instead of a bunch of arguments unless you splat it?

pjstirling
Posts: 166
Joined: Sun Nov 28, 2010 4:21 pm

Re: Starting out with Lisp - stuck on a macro

Post by pjstirling » Tue Jul 22, 2014 6:33 am

That gives:

Code: Select all

(MAPCAR (UPDATE-ROW (WHERE :RATING 6) :RATING 7) *DB*)
In general you should start writing macros by writing an example form (to be expanded), a result form (the desired expansion result), and the macro itself. Then you can get in a loop where you try to expand your example, and from that, you can modify one of the three, repeat until done!

Technically you can do macroexpansion using the MACROEXPAND-1 function in common-lisp from your repl, but slime makes it much easier than repeated copy-paste.

Slime is at http://common-lisp.net/project/slime/ (though you can also use quicklisp to keep a relatively recent version installed).

Paredit is also VERY useful, in terms of allowing editing of forms, rather than just characters. It doesn't have a proper website, but there's a page on the emacs wiki[1], which also has the download link. In particular the slurp and barf commands, and the kill s-exp I use regularly. The only gotcha with it is that if you accidentally push the insert key you can make it very confused.

[1] http://www.emacswiki.org/emacs/ParEdit

Plu
Posts: 3
Joined: Mon Jul 21, 2014 12:12 pm

Re: Starting out with Lisp - stuck on a macro

Post by Plu » Thu Jul 24, 2014 3:31 am

Thanks for the advice and help. I tried it in SLIME and that "C-c return" is super useful. And it's working now.

Back to the book and to some fiddling around.

Post Reply