i=0, j=1 k, l = 34, 65 [i, k] = [k, i]Each of these assignments corresponds to a different special form in Common Lisp:
(let* ((i 0) (j 1)) (multiple-value-bind (k l) (values 34 65) (destructuring-bind (i k) '(k i) ...)))Verbose and visually cluttered. When I realized returning multiple values was turning into such a pain it was turning me off values, I created the bind macro in response:
(bind (i 0) (j 1) (:mv (k l) (values 34 65)) (:db (i k) '(k i)) :do ...)Much better0,1. Here's how I implement bind:
(defmacro bind (&rest body) (apply 'bind-func body)) (defun bind-func (&rest body) (cond ((null (first body)) (error "no :do in bind")) ((eq (first body) :do) `(progn ,@(rest body))) (t (multiple-value-bind (let-form body) (determine-let-form body) (destructuring-bind ((a b) . body) body (if (eq let-form 'let) `(let ((,a ,b)) ,(apply 'bind-func body)) `(,let-form ,a ,b ,(apply 'bind-func body)))))))) (defun determine-let-form (form) (destructuring-bind ((a . rest) . body) form (cond ((eq a :db) (values 'destructuring-bind (cons rest body))) ((eq a :mv) (values 'multiple-value-bind (cons rest body))) (t (values 'let form)))))
(defun backward-or-up-sexp () (interactive) (if (eq (char-before (point)) ?\() (backward-up-list) (backward-sexp))) (defun forward-or-up-sexp () (interactive) (if (eq (char-after (point)) ?\)) (up-list) (forward-sexp))) (defun down-sexp () (interactive) (if (member (char-after (point)) '(?\n ?\))) (backward-sexp)) (down-list)) (global-set-key '(control left) 'backward-or-up-sexp) (global-set-key '(control right) 'forward-or-up-sexp) (global-set-key '(control up) 'backward-up-list) (global-set-key '(control down) 'down-sexp)