Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- (defmacro define-resetable-variable (name value)
- `(defparameter ,name (setf (get ',name 'initial-value) ,value)))
- (defun reset-variable (name)
- (let* ((absent (cons name name))
- (initval (get name 'initial-value absent)))
- (if (eql absent initval)
- (error "The variable ~S doesn't have a initial value defined." name)
- (setf (symbol-value name) initval))))
- (defmacro let-resettable-variables ((&rest bindings) &body body)
- (multiple-value-bind (docstrings declarations body) (parse-body :locally body)
- (let* ((vars (mapcar (lambda (binding) (if (listp binding) (first binding) binding)) bindings))
- (vals (mapcar (lambda (binding) (if (listp binding) (second binding) nil)) bindings))
- (initvars (mapcar (lambda (var) (gensym (symbol-name var))) vars)))
- `(let ,(mapcar (function list) initvars vals)
- (let ,(mapcar (function list) vars initvars)
- ,@declarations
- (flet ((reset-variable (name)
- (case name
- ,@(mapcar (lambda (var initvar) `((,var) (setf ,var ,initvar))) vars initvars)
- (otherwise (reset-variable name)))))
- ,@body))))))
- (define-resetable-variable *foo* 42)
- (assert (eql *foo* 42))
- (setf *foo* 33)
- (assert (eql *foo* 33))
- (reset-variable '*foo*)
- (assert (eql *foo* 42))
- (define-resetable-variable *bar* 24)
- (let-resettable-variables ((*bar* 33)
- (x 1)
- (y 2))
- (declare (integer x y))
- (let ((z 3))
- (assert (eql *foo* 42))
- (assert (eql *bar* 33))
- (assert (eql x 1))
- (assert (eql y 2))
- (setf *foo* 0
- *bar* 1
- x 2)
- (assert (eql *foo* 0))
- (assert (eql *bar* 1))
- (assert (eql x 2))
- (assert (eql y 2))
- (reset-variable '*foo*)
- (assert (eql *foo* 42))
- (assert (eql *bar* 1))
- (assert (eql x 2))
- (assert (eql y 2))
- (reset-variable '*bar*)
- (assert (eql *foo* 42))
- (assert (eql *bar* 33))
- (assert (eql x 2))
- (assert (eql y 2))
- (reset-variable 'x)
- (assert (eql *foo* 42))
- (assert (eql *bar* 33))
- (assert (eql x 1))
- (assert (eql y 2))
- (reset-variable 'y)
- (assert (eql *foo* 42))
- (assert (eql *bar* 33))
- (assert (eql x 1))
- (assert (eql y 2))
- (assert (handler-case (progn (reset-variable 'z) nil)
- (error () t)))
- (assert (handler-case (progn (reset-variable ':not-a-variable-at-all) nil)
- (error () t)))))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement