* 2010-09-05 14:24 (+0200), Kazimir Majorinc wrote:
Imagine that someone invited you to write the presentation "Five best CL macros ... I seen" or "Five best CL macros ... I wrote." What would you chose and why?
Just regular syntactic abstractions here. I wanted to execute a series of regular expression replacements for a string:
(with-regexp-series STRING ("[^a-z0-9._-]" "_") ;forms are ("regexp" "replacement") ("[_-]*\.+[_-]*" ".") ("_*-+_*" "-") ("([._-])\1+" "\1") ("^_+(.)" "\1") ("(.)_+$" "\1"))
The macros:
(defmacro with-value-passing ((var expression) &body body) `(let ((,var ,expression)) ,@(loop for top-level in body collect `(setf ,var ,top-level))))
(defmacro with-regexp-series (string &rest clauses) (let ((value (gensym))) `(with-value-passing (,value ,string) ,@(loop for clause in clauses collect `(ppcre:regex-replace-all ,(first clause) ,value ,(second clause))))))
WITH-VALUE-PASSING is a general-purpose macro which binds a new variable (VAR) and gives it the value of EXPRESSION. Then every top-level form in the macro's body is evaluated and each time the value is assigned to the VAR. It's just a way to run series of commands that depend on previous command's return value. I think it's more readable than deeply nested function calls.