8

It it possible to declare functions whose names are only available in the scope of another function, similar to let?

e.g.:

(defun my-fn (x y) 
  (let ((my-local-fn (lambda (a b) (message "%S" (- a b)))))
    (my-local-fn x y)
    (my-local-fn y x))
sds
  • 5,928
  • 20
  • 39
ideasman42
  • 8,375
  • 1
  • 28
  • 105
  • 2
    @Dan answered your question. In addition, in Emacs Lisp, as in Common Lisp, you can nest `defun` (or `cl-defun`) definitions, but that does not control definition scope: each `defun` is interpreted globally. This differs from Scheme's `define`, for example. See https://stackoverflow.com/a/34893747/729907 (Common Lisp question). – Drew Jul 12 '19 at 23:16
  • It's rare for code to actually use this. In practice you'll see packages to define a global helper function instead. – wasamasa Jul 13 '19 at 09:38

3 Answers3

10

You can also do it without resorting to cl-lib as follows:

(defun my-fn (x y) 
  (let ((my-local-fn (lambda (a b) (message "%S" (- a b)))))
    (funcall my-local-fn x y)
    (funcall my-local-fn y x))
Stefan
  • 26,154
  • 3
  • 46
  • 84
8

You can use cl-flet or cl-labels from cl-lib. The docstrings:

(cl-flet ((FUNC ARGLIST BODY...) ...) FORM...)

  Probably introduced at or before Emacs version 24.3.

Make local function definitions.
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.



(cl-labels ((FUNC ARGLIST BODY...) ...) FORM...)

  Probably introduced at or before Emacs version 24.3.

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.
Dan
  • 32,584
  • 6
  • 98
  • 168
2

Note: see Stefan's anwser.

It seems that local functions are not a native feature of the language. The GNU Reference Manual does not cover "local functions" or mention it.

Edit: Lisp manages objects unlike other languages. The function object returned the lambda form is bound to a local variable. It is a matter of symbols and scope values.

(defun foo (a b)
  (+ a b))

(let (foo)
  (setq val (symbol-value 'foo))
  (symbol-function 'foo))

(symbol-function 'foo) returns (lambda (a b) (+ a b)) whereas (symbol-value 'foo) returns nil.

Nevertheless, this feature is provided by the GNU Emacs Common Lisp Emulation (c.f. Function Bindings) which is a compatibility extension with Common Lisp for Elisp.

(cl-flet ((func (a b) (+ a b)))
  (func 1 1))