3

How does one access the declare specification of a function?

Edit: After the answer of npostavs I have to correct myself.

As long as a function is not byte-compiled the declare forms are still in its symbol-function. Where do they go after byte-compilation?

Example: (content of scratch buffer with lisp code and evaluation results)

(defun test (&rest args)
  "Function with declare form."
  (declare (indent 1))
  (interactive)
  (message args))
;; repl: test

(symbol-function 'test)
;; repl: (lambda (&rest args) "Function with declare form." (interactive) (message args))

(symbol-plist 'test)
;; repl: (lisp-indent-function 1)

That means the declare forms are not contained in the function cell of the symbol after the defun.

(defun test (&rest args)
  "Function with declare form."
  (interactive)
  (declare (indent 1))
  (message args))

(symbol-function 'test)
(lambda (&rest args) "Function with declare form." (interactive) (declare (indent 1)) (message args))

(setf f (byte-compile 'test))
#[(&rest args) "\301!\207" [args message] 2 "Function with declare form." nil]

What is the right way to access the declare information of a function in elisp?

Tobias
  • 32,569
  • 1
  • 34
  • 75

1 Answers1

6

Actually you have the declare in the wrong place, it should go before (interactive):

(defun test (&rest args)
  "Function with declare form."
  (declare (indent 1))
  (interactive)
  (message args))

Then if you macroexpand you can see what it does:

(prog1
    (defalias 'test
      #'(lambda
          (&rest args)
          "Function with declare form."
          (interactive)
          (message args)))
  (put 'test 'lisp-indent-function '1))

As you can see, the declare form itself is not stored, but defun interprets and rewrites it into code with the needed effect. Also note that the effect works on the symbol, not the function itself.

To reconstruct a declare form you would have to see what each kind of declaration does; the effects are listed in defun-declarations-alist and macro-declarations-alist (you can see this by looking at the definitions of defun and defmacro). Almost all work by putting a property on the symbol, so you could just get the corresponding property. The only exception (as of Emacs 24.5) is advertised-calling-convention which stores the preferred signature in advertised-signature-table, a hash table with the function itself as the key.

npostavs
  • 9,033
  • 1
  • 21
  • 53
  • And a good answer. – Drew Jan 03 '16 at 03:49
  • This is almost the right answer and I will mark it as such primarily because of its simplicity. You ask: "Why the 'almost'?" Because the information could be stored at some other place, e.g., an hash-table that captures all functions with `declare` forms. The right path to go is to look at `defmacro`, `defun` and most important `defun-declarations-alist` where the function properties and their actions are defined. Maybe, it is even possible to reconstruct the `declare` forms via the comparison of the symbol properties with the elements of `defun-declarations-alist`. Difficult: (e.g., `debug`). – Tobias Jan 03 '16 at 06:05
  • @Tobias ah, good point about `defun-declarations-alist`, I added some info about that to the answer. `debug` is not more difficult than the other declarations though. – npostavs Jan 03 '16 at 13:48