Evaluar docstring en macros

Sep 27 2020

Las macros como defun(o en defmacrosí mismas) tienen un docstringargumento opcional , pero como son macros y no funciones, docstringno se evalúan, sino que se toman tal cual.

Necesito que me docstringevalúen para que, en lugar de algo como esto,

"does a, then b, then c" ; b is hardcoded

Puedo poner algo como esto en su lugar:

(concat "does a, then " (getenv "<some-shell-variable>") " , then c") ; b isn't hardcoded

¿Es posible hacer esto sin tener que modificar las definiciones de defuny defmacro?

Por tweak, no me refiero a sobrescribir las definiciones, sino a escribir nuevas macros como prefix-defuny prefix-defmacrobasadas en las definiciones existentes de defuny demacro, excepto que la cadena de documentos se evalúa reemplazando todas las instancias de docstringcon (eval docstring).

Respuestas

1 Drew Sep 28 2020 at 03:33

Puede establecer la cadena de documentos de cualquier función, variable o cara a cualquier cadena que desee, ya sea (generada dinámicamente o no).

Para una función foo, coloque la cadena que desee en el símbolo foocomo valor de propiedad function-documentation:

(defun foo () ; `foo' gets no doc string from this defun.
  (interactive)
  (message "FOOOOOOOO"))

(put 'foo 'function-documentation "I'm `foo'.") ; Give function `foo' a doc string.
(put 'foo 'function-documentation "I'm NEW `foo' doc.") ; Redefine the doc string.

Lo mismo para defvar o defcustom: use la propiedad de símbolo variable-documentation:

(defvar foo 42) ; Variable `foo' has no doc string.

(put 'foo 'variable-documentation "I'm `foo'.") ; Give var `foo' a doc string.
(put 'foo 'variable-documentation "I'm NEW `foo' .") ; Redefine the doc string.

Consulte el manual de Elisp, Conceptos básicos de documentación del nodo y sus subnodos.

Lo mismo para defface: use la propiedad del símbolo variable-documentation. Pero deffacerequiere una cadena de documentos. No obstante, puede cambiarlo dinámicamente, como puede hacerlo para una función o variable.

(defface foo '((t :foreground "Red")) "0000") ; Doc string "0000".

(put 'foo 'face-documentation "11111") ; Change doc string to "1111".
2 phils Sep 27 2020 at 19:47
(defun foo ()
  (:documentation (concat "does a, then " (getenv "<some-shell-variable>") " , then c"))
  ...BODY...)

Esto es efectivamente un duplicado de ¿Es posible adjuntar una cadena de documentos generada a una lambda? excepto que esa pregunta está muy lambdaorientada, por lo que la respuesta de Stefan no indica que puedas hacer lo mismo con defun.

Si necesita que la cadena de documentos esté evalbajo demanda (es decir, cada vez que la solicite), también puede hacerlo, pero aparentemente no con :documentation. Consulte mi respuesta a la pregunta anterior para conocer algunas opciones para hacerlo.