changeset 5550:b908c7265a2b

Add the #'apply-partially API, as used by GNU. lisp/ChangeLog addition: 2011-08-12 Aidan Kehoe <kehoea@parhasard.net> * cl-macs.el: * cl-macs.el (apply-partially): New compiler macro. * subr.el: * subr.el (apply-partially): New. Sync this function's API and docstring from GNU. The implementation is mine and trivial; the compiler macro in cl-macs.el ensures that partially-applied functions in compiled code are also compiled. tests/ChangeLog addition: 2011-08-12 Aidan Kehoe <kehoea@parhasard.net> * automated/lisp-tests.el: Trivial tests of #'apply-partially, just added to subr.el.
author Aidan Kehoe <kehoea@parhasard.net>
date Fri, 12 Aug 2011 16:02:30 +0100
parents 493c487cbc3f
children 40a52efbf3a3 62edcc6a11ec
files lisp/ChangeLog lisp/cl-macs.el lisp/subr.el tests/ChangeLog tests/automated/lisp-tests.el
diffstat 5 files changed, 56 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/ChangeLog	Wed Aug 10 16:50:37 2011 +0100
+++ b/lisp/ChangeLog	Fri Aug 12 16:02:30 2011 +0100
@@ -1,3 +1,14 @@
+2011-08-12  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* cl-macs.el:
+	* cl-macs.el (apply-partially): New compiler macro.
+	* subr.el:
+	* subr.el (apply-partially): New.
+	Sync this function's API and docstring from GNU. The
+	implementation is mine and trivial; the compiler macro in
+	cl-macs.el ensures that partially-applied functions in compiled
+	code are also compiled.
+
 2011-08-10  Aidan Kehoe  <kehoea@parhasard.net>
 
 	* keymap.el:
--- a/lisp/cl-macs.el	Wed Aug 10 16:50:37 2011 +0100
+++ b/lisp/cl-macs.el	Fri Aug 12 16:02:30 2011 +0100
@@ -3510,6 +3510,24 @@
 	    (list 'let (list (list temp val)) (subst temp val res)))))
     form))
 
+(define-compiler-macro apply-partially (&whole form &rest args)
+  "Generate a #'make-byte-code call for #'apply-partially, if appropriate."
+  (if (< (length args) 1)
+      form
+    (if (cl-const-exprs-p args)
+        `#'(lambda (&rest args) (apply ,@args args))
+      (let* ((placeholders (mapcar 'quote-maybe (mapcar 'gensym args)))
+             (compiled (byte-compile-sexp
+                        `#'(lambda (&rest args) (apply ,@placeholders args)))))
+        `(make-byte-code
+          ',(compiled-function-arglist compiled)
+          ,(compiled-function-instructions compiled)
+          (vector ,@(sublis (pairlis placeholders args)
+                            (mapcar 'quote-maybe
+                                    (compiled-function-constants compiled))
+                            :test 'equal))
+          ,(compiled-function-stack-depth compiled))))))
+
 (define-compiler-macro delete-dups (list)
   `(delete-duplicates (the list ,list) :test #'equal :from-end t))
 
--- a/lisp/subr.el	Wed Aug 10 16:50:37 2011 +0100
+++ b/lisp/subr.el	Fri Aug 12 16:02:30 2011 +0100
@@ -85,6 +85,19 @@
 quote lambda expressions appropriately."
   `(function (lambda ,@cdr)))
 
+;; Partial application of functions (related to currying).  XEmacs; closures
+;; aren't yet available to us as a language type, but they're not necessary
+;; for this function (nor indeed is CL's #'lexical-let).  See also the
+;; compiler macro in cl-macs.el, which generates a call to #'make-byte-code
+;; at runtime, ensuring that partially applied functions are byte-compiled.
+(defun apply-partially (function &rest args)
+  "Return a function that is a partial application of FUNCTION to ARGS.
+ARGS is a list of the first N arguments to pass to FUNCTION.
+The result is a new function which does the same as FUNCTION, except that
+the first N arguments are fixed at the values with which this function
+was called."
+  `(lambda (&rest args) (apply ',function ,@(mapcar 'quote-maybe args) args)))
+
 ;; FSF 21.2 has various basic macros here.  We don't because they're either
 ;; in cl*.el (which we dump and hence is always available) or built-in.
 
--- a/tests/ChangeLog	Wed Aug 10 16:50:37 2011 +0100
+++ b/tests/ChangeLog	Fri Aug 12 16:02:30 2011 +0100
@@ -1,3 +1,8 @@
+2011-08-12  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* automated/lisp-tests.el:
+	Trivial tests of #'apply-partially, just added to subr.el.
+
 2011-08-08  Stephen J. Turnbull  <stephen@xemacs.org>
 
 	* automated/syntax-tests.el:
--- a/tests/automated/lisp-tests.el	Wed Aug 10 16:50:37 2011 +0100
+++ b/tests/automated/lisp-tests.el	Fri Aug 12 16:02:30 2011 +0100
@@ -2926,4 +2926,13 @@
   (Assert (equal '([symbol expansion] [copy expansion] [third expansion])
 		 (test-symbol-macrolet))))
 
+;; Basic tests of #'apply-partially.
+(let* ((four 4)
+       (times-four (apply-partially '* four))
+       (plus-twelve (apply-partially '+ 6 (* 3 2))))
+  (Assert (eql (funcall times-four 6) 24))
+  (Assert (eql (funcall times-four 4 4) 64))
+  (Assert (eql (funcall plus-twelve (funcall times-four 4) 4 4) 36))
+  (Check-Error wrong-number-of-arguments (apply-partially)))
+
 ;;; end of lisp-tests.el