]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix #'fun handling inside `labels' (Bug#31792)
authorNoam Postavsky <npostavs@gmail.com>
Tue, 12 Jun 2018 22:41:46 +0000 (18:41 -0400)
committerNoam Postavsky <npostavs@gmail.com>
Wed, 20 Jun 2018 00:02:16 +0000 (20:02 -0400)
* lisp/emacs-lisp/cl.el (labels): Apply the equivalent of the
cl-labels change from 2015-01-16 "* lisp/emacs-lisp/cl-macs.el: Fix
last change".
* test/lisp/emacs-lisp/cl-tests.el (labels-function-quoting): New
test.
* lisp/emacs-lisp/cl-macs.el (cl-flet, cl-labels): Improve docstring,
link to relevant manual page.
* doc/misc/cl.texi (Function Bindings): Don't imply that function
cells of symbols are modified by cl-flet.  Don't claim that cl-flet or
cl-labels affect references of the form (quote FUNC).

doc/misc/cl.texi
lisp/emacs-lisp/cl-macs.el
lisp/emacs-lisp/cl.el
test/lisp/emacs-lisp/cl-tests.el [new file with mode: 0644]

index bf85b00e937903997ee4344eafb53176a35e5508..553b935b1ef0828ab221d227c4d241b3c5fae478 100644 (file)
@@ -1299,17 +1299,18 @@ These forms make @code{let}-like bindings to functions instead
 of variables.
 
 @defmac cl-flet (bindings@dots{}) forms@dots{}
-This form establishes @code{let}-style bindings on the function
-cells of symbols rather than on the value cells.  Each @var{binding}
-must be a list of the form @samp{(@var{name} @var{arglist}
-@var{forms}@dots{})}, which defines a function exactly as if
-it were a @code{cl-defun} form.  The function @var{name} is defined
-accordingly but only within the body of the @code{cl-flet}, hiding any external
-definition if applicable.
+This form establishes @code{let}-style bindings for functions rather
+than values.  Each @var{binding} must be a list of the form
+@samp{(@var{name} @var{arglist} @var{body}@dots{})}.  Within
+@var{forms}, any reference to the function @var{name} uses the local
+definition instead of the global one.
+
+A ``reference'' to a function name is either a call to that function,
+or a use of its name quoted by @code{function} to be passed on to,
+say, @code{mapcar}.
 
 The bindings are lexical in scope.  This means that all references to
-the named functions must appear physically within the body of the
-@code{cl-flet} form.
+the named functions must appear physically within @var{forms}.
 
 Functions defined by @code{cl-flet} may use the full Common Lisp
 argument notation supported by @code{cl-defun}; also, the function
@@ -1336,10 +1337,6 @@ functions must appear physically within the body of the
 the functions themselves.  Thus, @code{cl-labels} can define
 local recursive functions, or mutually-recursive sets of functions.
 
-A ``reference'' to a function name is either a call to that
-function, or a use of its name quoted by @code{quote} or
-@code{function} to be passed on to, say, @code{mapcar}.
-
 Note that the @file{cl.el} version of this macro behaves slightly
 differently.  @xref{Obsolete Macros}.
 @end defmac
index 9c47ceae18ee702f10ded3bb7d0612ed3eaca5a4..0854e665b9b4cb1b0744a53f8893ce15e7ca0ba1 100644 (file)
@@ -1964,13 +1964,16 @@ a `let' form, except that the list of symbols can be computed at run-time."
 ;;;###autoload
 (defmacro cl-flet (bindings &rest body)
   "Make local function definitions.
-Like `cl-labels' but the definitions are not recursive.
-Each binding can take the form (FUNC EXP) where
+Each definition can take the form (FUNC EXP) where
 FUNC is the function name, and EXP is an expression that returns the
 function value to which it should be bound, or it can take the more common
 form \(FUNC ARGLIST BODY...) which is a shorthand
 for (FUNC (lambda ARGLIST BODY)).
 
+FUNC is defined only within FORM, not BODY, so you can't write
+recursive function definitions.  Use `cl-labels' for that.  See
+info node `(cl) Function Bindings' for details.
+
 \(fn ((FUNC ARGLIST BODY...) ...) FORM...)"
   (declare (indent 1) (debug ((&rest (cl-defun)) cl-declarations body)))
   (let ((binds ()) (newenv macroexpand-all-environment))
@@ -2012,9 +2015,13 @@ Like `cl-flet' but the definitions can refer to previous ones.
 
 ;;;###autoload
 (defmacro cl-labels (bindings &rest body)
-  "Make temporary function bindings.
-The bindings can be recursive and the scoping is lexical, but capturing them
-in closures will only work if `lexical-binding' is in use.
+    "Make local (recursive) function definitions.
+Each definition can take the form (FUNC ARGLIST BODY...) where
+FUNC is the function name, ARGLIST its arguments, and BODY the
+forms of the function body.  FUNC is defined in any BODY, as well
+as FORM, so you can write recursive and mutually recursive
+function definitions.  See info node `(cl) Function Bindings' for
+details.
 
 \(fn ((FUNC ARGLIST BODY...) ...) FORM...)"
   (declare (indent 1) (debug cl-flet))
index d53c8e0bbcf3af101d93b43d97cdbf09807a3a26..f6643158d2d9f8bac20411fdde11d65401530538 100644 (file)
@@ -466,9 +466,12 @@ rather than relying on `lexical-binding'."
        (push var sets)
        (push (cons (car binding)
                     `(lambda (&rest cl-labels-args)
-                       (cl-list* 'funcall ',var
-                                 cl-labels-args)))
+                       (if (eq (car cl-labels-args) cl--labels-magic)
+                           (list cl--labels-magic ',var)
+                         (cl-list* 'funcall ',var cl-labels-args))))
               newenv)))
+    ;; `lexical-let' adds `cl--function-convert' (which calls
+    ;; `cl--labels-convert') as a macroexpander for `function'.
     (macroexpand-all `(lexical-let ,vars (setq ,@sets) ,@body) newenv)))
 
 ;; Generalized variables are provided by gv.el, but some details are
diff --git a/test/lisp/emacs-lisp/cl-tests.el b/test/lisp/emacs-lisp/cl-tests.el
new file mode 100644 (file)
index 0000000..b673822
--- /dev/null
@@ -0,0 +1,35 @@
+;;; cl-tests.el --- tests for emacs-lisp/cl.el  -*- lexical-binding:t -*-
+
+;; Copyright (C) 2018 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see `https://www.gnu.org/licenses/'.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'cl)
+(require 'ert)
+
+\f
+
+(ert-deftest labels-function-quoting ()
+  "Test that #'foo does the right thing in `labels'." ; Bug#31792.
+  (should (eq (funcall (labels ((foo () t))
+                         #'foo))
+              t)))
+
+;;; cl-tests.el ends here