Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Common Lisp - Get docstring from methods AND functions?

This is a follow up to this previously asked question about the documentation function, which apparently deserved its own post.

Is there a way to dynamically get the docstring of either a function/macro OR a method in SBCL?

So far (documentation function-name 'function) gets me the docstring for regular functions (and I assume macros as well), but not methods. I tried 'method, 'standard-method and even 't but they don't seem to work.

My problem is that the environment I work with (in a visual programming interface based on Lisp) is filled with little engines that can be either functions or methods and I don't know how to differentiate them. I just need users to be able to get the docstring quickly for any given symbol (or tool) in the library, no matter its type, if it exists of course.

Thanks !

Julien

like image 328
Julien Vincenot Avatar asked Jul 13 '18 10:07

Julien Vincenot


1 Answers

Symbols name functions, including macros and generic-functions, but not methods. In order to uniquely identify a method, you need to know the generic-function and all the applicable modifiers and specializers.

For example, PRINT-OBJECT names a generic function, but is not sufficient to refer to a specific methods. You can however iterate over all methods specializing a generic function and manipulate their documentation: instead of passing a name to DOCUMENTATION, you give the function object and T. In order to do this portably, use closer-mop:

(ql:quickload :closer-mop)

For example:

(lambda (generic-function)
  (map 'list
       (lambda (method) (documentation method t))
       (closer-mop:generic-function-methods generic-function)))
=> #<FUNCTION (LAMBDA (GENERIC-FUNCTION)) {1001BBCD3B}>

Let's try it:

CL-USER> (funcall * #'documentation)
(NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL)

Oops.

CL-USER> (defmethod documentation ((test (eql :test)) _) 
             "Test documentation" 
           "Returned value")
...
CL-USER> (documentation :test t)
"Returned value"

CL-USER> (funcall *** #'documentation)
("Test documentation" NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL)
like image 80
coredump Avatar answered Sep 28 '22 06:09

coredump