comparison lisp/cl-macs.el @ 5326:60ba780f9078

Use defmacro* when defining dolist, dotimes, do-symbols, macrolet, cl-macs.el 2011-01-01 Aidan Kehoe <kehoea@parhasard.net> * cl-macs.el (dolist, dotimes, do-symbols, macrolet) (symbol-macrolet): Define these macros with defmacro* instead of parsing the argument list by hand, for the sake of style and readability; use backquote where appropriate, instead of calling #'list and and friends, for the same reason.
author Aidan Kehoe <kehoea@parhasard.net>
date Sun, 02 Jan 2011 00:06:14 +0000
parents 8aa511adfad6
children 7b391d07b334
comparison
equal deleted inserted replaced
5325:47298dcf2e8f 5326:60ba780f9078
1677 'setq 'psetq) 1677 'setq 'psetq)
1678 (apply 'append sets))))))) 1678 (apply 'append sets)))))))
1679 (or (cdr endtest) '(nil))))) 1679 (or (cdr endtest) '(nil)))))
1680 1680
1681 ;;;###autoload 1681 ;;;###autoload
1682 (defmacro dolist (spec &rest body) 1682 (defmacro* dolist ((var list &optional result) &body body)
1683 "Loop over a list. 1683 "Loop over a list.
1684 Evaluate BODY with VAR bound to each `car' from LIST, in turn. 1684 Evaluate BODY with VAR bound to each `car' from LIST, in turn.
1685 Then evaluate RESULT to get return value, default nil. 1685 Then evaluate RESULT to get return value, default nil."
1686 1686 (let ((gensym (gensym)))
1687 arguments: ((VAR LIST &optional RESULT) &body BODY)" 1687 `(block nil
1688 (let ((temp (gensym "--dolist-temp--"))) 1688 (let ((,gensym ,list) ,var)
1689 (list 'block nil 1689 (while ,gensym
1690 (list* 'let (list (list temp (nth 1 spec)) (car spec)) 1690 (setq ,var (car ,gensym))
1691 (list* 'while temp (list 'setq (car spec) (list 'car temp)) 1691 ,@body
1692 (append body (list (list 'setq temp 1692 (setq ,gensym (cdr ,gensym)))
1693 (list 'cdr temp))))) 1693 ,@(if result `((setq ,var nil) ,result))))))
1694 (if (cdr (cdr spec)) 1694
1695 (cons (list 'setq (car spec) nil) (cdr (cdr spec))) 1695 ;;;###autoload
1696 '(nil)))))) 1696 (defmacro* dotimes ((var count &optional result) &body body)
1697
1698 ;;;###autoload
1699 (defmacro dotimes (spec &rest body)
1700 "Loop a certain number of times. 1697 "Loop a certain number of times.
1701 Evaluate BODY with VAR bound to successive integers from 0, inclusive, 1698 Evaluate BODY with VAR bound to successive integers from 0, inclusive,
1702 to COUNT, exclusive. Then evaluate RESULT to get return value, default 1699 to COUNT, exclusive. Then evaluate RESULT to get return value, default
1703 nil. 1700 nil."
1704 1701 (let* ((limit (if (cl-const-expr-p count) count (gensym)))
1705 arguments: ((VAR COUNT &optional RESULT) &body BODY)" 1702 (bind (if (cl-const-expr-p count) nil `((,limit ,count)))))
1706 (let ((temp (gensym "--dotimes-temp--"))) 1703 `(block nil
1707 (list 'block nil 1704 (let ((,var 0) ,@bind)
1708 (list* 'let (list (list temp (nth 1 spec)) (list (car spec) 0)) 1705 (while (< ,var ,limit)
1709 (list* 'while (list '< (car spec) temp) 1706 ,@body
1710 (append body (list (list 'incf (car spec))))) 1707 (setq ,var (1+ ,var)))
1711 (or (cdr (cdr spec)) '(nil)))))) 1708 ,@(if result (list result))))))
1712 1709
1713 ;;;###autoload 1710 ;;;###autoload
1714 (defmacro do-symbols (spec &rest body) 1711 (defmacro* do-symbols ((var &optional obarray result) &rest body)
1715 "Loop over all symbols. 1712 "Loop over all interned symbols.
1716 Evaluate BODY with VAR bound to each interned symbol, or to each symbol 1713 Evaluate BODY with VAR bound to each interned symbol, or to each symbol
1717 from OBARRAY. 1714 from OBARRAY."
1718 1715 `(block nil
1719 arguments: ((VAR &optional OBARRAY RESULT) &body BODY)" 1716 (mapatoms #'(lambda (,var) ,@body) ,@(and obarray (list obarray)))
1720 ;; Apparently this doesn't have an implicit block. 1717 ,@(if result `((let (,var) ,result)))))
1721 (list 'block nil
1722 (list 'let (list (car spec))
1723 (list* 'mapatoms
1724 (list 'function (list* 'lambda (list (car spec)) body))
1725 (and (cadr spec) (list (cadr spec))))
1726 (caddr spec))))
1727 1718
1728 ;;;###autoload 1719 ;;;###autoload
1729 (defmacro do-all-symbols (spec &rest body) 1720 (defmacro do-all-symbols (spec &rest body)
1730 (list* 'do-symbols (list (car spec) nil (cadr spec)) body)) 1721 (list* 'do-symbols (list (car spec) nil (cadr spec)) body))
1731 1722
1804 cl-macro-environment))) 1795 cl-macro-environment)))
1805 1796
1806 ;; The following ought to have a better definition for use with newer 1797 ;; The following ought to have a better definition for use with newer
1807 ;; byte compilers. 1798 ;; byte compilers.
1808 ;;;###autoload 1799 ;;;###autoload
1809 (defmacro macrolet (bindings &rest body) 1800 (defmacro* macrolet (((name arglist &optional docstring &body body)
1801 &rest macros) &body form)
1810 "Make temporary macro definitions. 1802 "Make temporary macro definitions.
1811 This is like `flet', but for macros instead of functions. 1803 This is like `flet', but for macros instead of functions."
1812 1804 (cl-macroexpand-all (cons 'progn form)
1813 arguments: (((NAME ARGLIST &optional DOCSTRING &body body) &rest MACROS) &body FORM)" 1805 (nconc
1814 (if (cdr bindings) 1806 (loop
1815 (list 'macrolet 1807 for (name . details)
1816 (list (car bindings)) (list* 'macrolet (cdr bindings) body)) 1808 in (cons (list* name arglist docstring body) macros)
1817 (if (null bindings) (cons 'progn body) 1809 collect
1818 (let* ((name (caar bindings)) 1810 (list* name 'lambda
1819 (res (cl-transform-lambda (cdar bindings) name))) 1811 (prog1
1820 (eval (car res)) 1812 (cdr (setq details (cl-transform-lambda
1821 (cl-macroexpand-all (cons 'progn body) 1813 details name)))
1822 (cons (list* name 'lambda (cdr res)) 1814 (eval (car details)))))
1823 cl-macro-environment)))))) 1815 cl-macro-environment)))
1824 1816
1825 ;;;###autoload 1817 ;;;###autoload
1826 (defmacro symbol-macrolet (bindings &rest body) 1818 (defmacro* symbol-macrolet (((name expansion) &rest symbol-macros) &body form)
1827 "Make symbol macro definitions. 1819 "Make symbol macro definitions.
1828 Within the body FORMs, references to the variable NAME will be replaced 1820 Within the body FORMs, references to the variable NAME will be replaced
1829 by EXPANSION, and (setq NAME ...) will act like (setf EXPANSION ...). 1821 by EXPANSION, and (setq NAME ...) will act like (setf EXPANSION ...)."
1830 1822 (cl-macroexpand-all (cons 'progn form)
1831 arguments: (((NAME EXPANSION) &rest SYMBOL-MACROS) &body FORM)" 1823 (append (list (list (symbol-name name) expansion))
1832 (if (cdr bindings) 1824 (loop
1833 (list 'symbol-macrolet 1825 for (name expansion) in symbol-macros
1834 (list (car bindings)) (list* 'symbol-macrolet (cdr bindings) body)) 1826 collect (list (symbol-name name) expansion))
1835 (if (null bindings) (cons 'progn body) 1827 cl-macro-environment)))
1836 (cl-macroexpand-all (cons 'progn body)
1837 (cons (list (symbol-name (caar bindings))
1838 (cadar bindings))
1839 cl-macro-environment)))))
1840 1828
1841 (defvar cl-closure-vars nil) 1829 (defvar cl-closure-vars nil)
1842 ;;;###autoload 1830 ;;;###autoload
1843 (defmacro lexical-let (bindings &rest body) 1831 (defmacro lexical-let (bindings &rest body)
1844 "Like `let', but lexically scoped. 1832 "Like `let', but lexically scoped.