mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-11-23 07:19:15 +00:00
Fix #'fun handling inside `labels' (Bug#31792)
* 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).
This commit is contained in:
parent
36737705b4
commit
e292c0973c
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
35
test/lisp/emacs-lisp/cl-tests.el
Normal file
35
test/lisp/emacs-lisp/cl-tests.el
Normal file
@ -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)
|
||||
|
||||
|
||||
|
||||
(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
|
Loading…
Reference in New Issue
Block a user