carbon2-commit: Add Common Lisp's #'complement to cl-extra.el.
Aidan Kehoe
kehoea at parhasard.net
Fri Jun 4 06:23:42 EDT 2010
changeset: 5280:7789ae555c45
user: Aidan Kehoe <kehoea at parhasard.net>
date: Wed Jun 02 16:18:50 2010 +0100
files: lisp/ChangeLog lisp/cl-extra.el lisp/cl-macs.el
description:
Add Common Lisp's #'complement to cl-extra.el.
2010-06-02 Aidan Kehoe <kehoea at parhasard.net>
* cl-macs.el (complement):
* cl-extra.el (complement):
Add an implementation and a compiler macro for #'complement, as
specified by CL. For discussion; the compiler macro may be a
little too aggressive about taking the compile time argument lists
of the functions it is inverting.
diff -r 1086297242fe -r 7789ae555c45 lisp/ChangeLog
--- a/lisp/ChangeLog Wed Jun 02 15:31:15 2010 +0100
+++ b/lisp/ChangeLog Wed Jun 02 16:18:50 2010 +0100
@@ -1,3 +1,12 @@
+2010-06-02 Aidan Kehoe <kehoea at parhasard.net>
+
+ * cl-macs.el (complement):
+ * cl-extra.el (complement):
+ Add an implementation and a compiler macro for #'complement, as
+ specified by CL. For discussion; the compiler macro may be a
+ little too aggressive about taking the compile time argument lists
+ of the functions it is inverting.
+
2010-05-31 Aidan Kehoe <kehoea at parhasard.net>
* specifier.el (current-display-table):
diff -r 1086297242fe -r 7789ae555c45 lisp/cl-extra.el
--- a/lisp/cl-extra.el Wed Jun 02 15:31:15 2010 +0100
+++ b/lisp/cl-extra.el Wed Jun 02 16:18:50 2010 +0100
@@ -99,6 +99,14 @@
;; XEmacs; #'map, #'mapc, #'mapl, #'maplist, #'mapcon, #'some and #'every
;; are now in C, together with #'map-into, which was never in this file.
+
+;; The compiler macro for this in cl-macs.el means if #'complement is handed
+;; a constant expression, byte-compiled code will see a byte-compiled
+;; function.
+(defun complement (function &optional documentation)
+ "Return a function which gives the logical inverse of what FUNCTION would."
+ `(lambda (&rest arguments) ,@(if documentation (list documentation))
+ (not (apply ',function arguments))))
(defun notany (cl-pred cl-seq &rest cl-rest)
"Return true if PREDICATE is false of every element of SEQ or SEQs."
diff -r 1086297242fe -r 7789ae555c45 lisp/cl-macs.el
--- a/lisp/cl-macs.el Wed Jun 02 15:31:15 2010 +0100
+++ b/lisp/cl-macs.el Wed Jun 02 16:18:50 2010 +0100
@@ -3712,6 +3712,45 @@
(define-compiler-macro pairlis (a b &optional c)
`(nconc (mapcar* #'cons ,a ,b) ,c))
+(define-compiler-macro complement (&whole form fn)
+ (if (or (eq (car-safe fn) 'function) (eq (car-safe fn) 'quote))
+ (cond
+ ((and (symbolp (second fn)) (get (second fn) 'byte-compile-negated-op))
+ (list 'function (get (second fn) 'byte-compile-negated-op)))
+ ((and (symbolp (second fn)) (fboundp (second fn))
+ (compiled-function-p (indirect-function (second fn))))
+ (let* ((cf (indirect-function (second fn)))
+ (cfa (compiled-function-arglist cf))
+ (do-apply (memq '&rest cfa)))
+ `#'(lambda ,cfa
+ (not (,@(if do-apply `(apply ',(second fn)) (list (second fn)))
+ ,@(remq '&optional
+ (remq '&rest cfa)))))))
+ (t
+ `#'(lambda (&rest arguments)
+ (not (apply ,fn arguments)))))
+ ;; Determine the function to call at runtime.
+ (destructuring-bind
+ (arglist instructions constants stack-depth)
+ (let ((compiled-lambda
+ (byte-compile-sexp
+ #'(lambda (&rest arguments)
+ (not (apply 'placeholder arguments))))))
+ (list
+ (compiled-function-arglist compiled-lambda)
+ (compiled-function-instructions compiled-lambda)
+ (append (compiled-function-constants compiled-lambda) nil)
+ (compiled-function-stack-depth compiled-lambda)))
+ `(make-byte-code
+ ',arglist ,instructions (vector
+ ,@(nsublis
+ (list (cons (quote-maybe
+ 'placeholder)
+ fn))
+ (mapcar #'quote-maybe constants)
+:test #'equal))
+ ,stack-depth))))
+
(mapc
#'(lambda (y)
(put (car y) 'side-effect-free t)
More information about the XEmacs-Patches
mailing list