lispcommon-lisp

Multiple defparameter macro in Lisp?


I tried to write defparameter macro for arbitrary number of variables, starting from the working code for the single variable:

(defmacro defpar (name initial-value )                                                  
 `(progn (declaim (special ,name))                                                    
        (setf (symbol-value ',name) ,initial-value)                                  
         ',name)

Here is a modification

(defmacro defpar (&rest rest)
  (let ((i  (gensym)))
    `(let (,i)
;;     (declaim (special ,rest))
       (dotimes (,i  (/ (length ',rest) 2))
         (progn
           (print (list ,i ',rest))
           (setf (symbol-value ',(pop rest)) ',(pop rest))
           )
         ))))

Now:

(defpar S1 1)                                                                            
(print `("S1 = " ,S1))

gives

(0 (S1 1)) 
("S1 = " 1)

It is OK: S1 is defined and is equal to 1

and for two arguments

(defpar S1 1 S2 2)                                                                    
(print `("S1 = " ,S1  " S2 = " ,S2 )) 

gives

(0 (*S1* 1 *S2* 2))
(1 (*S1* 1 *S2* 2))
....  The variable *S2* is unbound.   

As I checked, rest list is the same at the new iteration in the loop, but I failed to update it. And I missed the special statement. (declaim (special ,rest)) comes to error in SBCL. Let me know if it is important.

Please, help me. May be it is already done, like in setf?


Solution

  • Just generate multiple defparameter forms?

    CL-USER 8 > (defmacro defpar (&rest var-and-value-list)
                  `(progn ,@(loop for (var value) on var-and-value-list by #'cddr
                                  collect `(defparameter ,var ,value))))
    DEFPAR
    
    CL-USER 9 > (pprint (macroexpand '(defpar a 1 b 2 c 3)))
    
    (PROGN (DEFPARAMETER A 1)
           (DEFPARAMETER B 2)
           (DEFPARAMETER C 3))
    

    The DEFPARAMETER expansion details varies between CL implementations

    Keep in mind that the macro expansion of DEFPARAMETER is not standardized in Common Lisp. Different implementations expand that into different forms. Many of them are also implementation specific. Additionally the expansion may provide features of a development environment, like recording the source code or recording the location of the source code. Thus it is best not to reinvent defparameter for multiple forms, but to reuse it. This makes sure that the implementation specific feature are still supported.