Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing a ++ macro in Common Lisp

I've been attempting to write a Lisp macro that would perfom the equivalent of ++ in other programming languages for semantic reasons. I've attempted to do this in several different ways, but none of them seem to work, and all are accepted by the interpreter, so I don't know if I have the correct syntax or not. My idea of how this would be defined would be

(defmacro ++ (variable)
  (incf variable))

but this gives me a SIMPLE-TYPE-ERROR when trying to use it. What would make it work?

like image 474
Cristián Romo Avatar asked Sep 15 '08 18:09

Cristián Romo


People also ask

How do you write a macro in Lisp?

Macros allow you to extend the syntax of standard LISP. Technically, a macro is a function that takes an s-expression as arguments and returns a LISP form, which is then evaluated.

How do Lisp macros work?

The Common Lisp macro facility allows the user to define arbitrary functions that convert certain Lisp forms into different forms before evaluating or compiling them. This is done at the expression level, not at the character-string level as in most other languages.

When would you use a macro Lisp?

A macro call involves computation at two times: when the macro is expanded, and when the expansion is evaluated. All the macroexpansion in a Lisp program is done when the program is compiled, and every bit of computation which can be done at compile-time is one bit that won't slow the program down when it's running.


2 Answers

Remember that a macro returns an expression to be evaluated. In order to do this, you have to backquote:

(defmacro ++ (variable)
   `(incf ,variable))
like image 142
Kyle Cronin Avatar answered Sep 28 '22 19:09

Kyle Cronin


Both of the previous answers work, but they give you a macro that you call as

(++ varname)

instead of varname++ or ++varname, which I suspect you want. I don't know if you can actually get the former, but for the latter, you can do a read macro. Since it's two characters, a dispatch macro is probably best. Untested, since I don't have a handy running lisp, but something like:

(defun plusplus-reader (stream subchar arg)
   (declare (ignore subchar arg))
   (list 'incf (read stream t nil t)))
(set-dispatch-macro-character #\+ #\+ #'plusplus-reader)

should make ++var actually read as (incf var).

like image 22
user10029 Avatar answered Sep 28 '22 21:09

user10029