Programmatically Setting Lisp Docstrings
I just updated my Elisp memoization function so that it’s no longer a dirty hack. To work around the lack of closures, due to the lack of lexical scope in Elisp, the original version used uninterned symbols to store the look-up table. The new version in the post uses lexical-let, which does the same thing internally to fake a closure. The new version in my dotfiles repository uses the brand new Emacs 24 lexical scoping.
It was “dirty” because it built a lambda function out of a list at run time, taking advantage of the way Elisp currently handles functions. The reason for this was that I wanted to inject the original documentation string into the new function which can’t normally be done when lambda is used the correct way. When I updated the function I fixed this as well. It uses a trick provided by Elisp, which is different than the Common Lisp way that I assumed.
Both Elisp and Common Lisp have a documentation function for programmatically accessing symbol documentation. The Elisp version only provides function documentation, so it only accepts one argument.
(defun foo ()
"Foo."
nil)
(documentation 'foo)
=> "Foo."
The Common Lisp version must be told what type of documentation to return, such as function or variable (defvar, defconst).
(documentation 'foo 'function)
=> "Foo."
As it might be expected, this is setf-able! It’s possible to update or modify documentation strings without needing to redefine the function.
(setf (documentation 'foo 'function) "New doc string.")
Unfortunately it’s not setf-able in Elisp. Instead you can set the function-documentation property of the symbol. The documentation function will prefer this over the string stored in the function itself.
(put 'foo 'function-documentation "Foo updated.")
(documentation 'foo)
=> "Foo updated."
The downside is that this is a second place to put docstrings, leading to surprising behavior for developers unaware of this hack.
(put 'foo 'function-documentation "Old docstring.")
(defun foo ()
"New docstring."
nil)
(documentation 'foo)
=> "Old docstring."
This can be fixed by setting the symbol property for function-documentation to nil.
(put 'foo 'function-documentation nil)
I prefer the Common Lisp method.
blog comments powered by Disqus