3
votes

I'll show the thing that I want from Common Lisp that already works in Elisp:

(defun square (x)
  (* x x))
(symbol-function 'square)
;; => (lambda (x) (* x x))

So by just knowing the symbol square, I want to retrieve its whole body. I've looked at CL's:

(function-lambda-expression #'square)
;; =>
(SB-INT:NAMED-LAMBDA SQUARE
    (X)
  (BLOCK SQUARE (* X X)))
NIL
SQUARE

The return result is close to what I need, but it only works sometimes. Most of the time, I get:

(function-lambda-expression #'list)
;; =>
NIL
T
LIST

Is there a more reliable function that does this? I'm aware of swank-backend:arglist that's very good at retrieving the arguments, but I can't find a retriever for the body there.

UPDATE

It seems that the general solution isn't possible in plain lisp. Is this possible to do in SLIME? Assume that I always have SLIME running, and all the code was loaded through there. Can the code be obtained more reliably than just using SLIME's goto-definition and copying the text from there?

3
You may also get more reliable results with other implementations. E.g., CLISP might save more data about definitions. (That's just a guess, based on a recent question, Strange behavior in Common Lisp.)Joshua Taylor
What are you really trying to do?Svante
I'm trying to implement a flatten-at-point operation for CL: take the function call at point and substitute the arguments into the function body. I already have one for Elisp and Clojure.abo-abo
How will you handle closures? How are you handling them in elisp and clojure? Why are you trying to do it under SLIME? It sounds like you're attempting some form of inlining, but at a level where you don't have enough information to know if you can actually perform it.acelent
Closures sort-of work for Elisp. The inlining is interactive, purely to speed up editing. If it works, it works. If it doesn't - oh well, I can still do it manually.abo-abo

3 Answers

6
votes

No. The saving of the source code at the symbol is not mandated by the standard, so any implementation may choose not to do that (this also has performance implications).

I guess that you might get that behaviour more often by declaiming optimize (debug 3), but I have not tried that; it is most likely implementation dependent.

Answer to update: Since you want to implement an editor functionality interacting with the Lisp image, I'd say that using the Lisp Interaction Mode (the LIM in SLIME) is exactly what you need to do.

1
votes

Perhaps the reason is that the system/core functions, like #'list, has been compiled for speed when the image was built? Perhaps if you bootstrapped SBCL yourself you could make one that was slower and had more information. Or you can just look the the source sode:

(describe #'list)

#<FUNCTION LIST>
  [compiled function]

Lambda-list: (&REST ARGS)
Declared type: (FUNCTION * (VALUES LIST &OPTIONAL))
Derived type: (FUNCTION (&REST T) (VALUES LIST &OPTIONAL))
Documentation:
  Return constructs and returns a list of its arguments.
Known attributes: flushable, unsafely-flushable, movable
Source file: SYS:SRC;CODE;LIST.LISP

That last line is correct since under src/code/list.lisp you actually find the definition.

Notice the behaviour of describe and function-lambda-expression are implementation dependent. Eg. in CLISP the output is completely different.

1
votes

(function-lambda-expression #'list) heretries to retrieve the code of a built-in function. Not every built-in function needs to have Lisp code as its implementation.

I haven't tried it, but maybe you can build SBCL yourself, such that it records the source code and saves it in the image.

For a standard image of SBCL I would not expect that it contains source code.