Returning the name of a function

6 views
Skip to first unread message

Coby Beck

unread,
Jan 17, 2000, 3:00:00 AM1/17/00
to
Hello,

I s there a function that will programmatically return the name of the
function definition in which it is called? ie:

(defun foo()
(format t "Hello, from inside of ~A" (magic-function)))

>(foo)
"Hello, from inside of FOO"
>

Is this feasible to do in Common Lisp? (I am using Allegro 5.01 in case
there is such a beast specific to that implementation.)

Coby


Christopher C Stacy

unread,
Jan 17, 2000, 3:00:00 AM1/17/00
to
"Coby Beck" <cb...@mercury.bc.ca> writes:
> I s there a function that will programmatically return the name of the
> function definition in which it is called? ie:

There isn't a function in Common Lisp that will tell you who the
calling function is up the stack. Individual implementations might
have an internal function that does something like that, and they
might document it. But it would by no means be normal to use such
a function. Rather, it would be intended for use by things like
the debugger.

If you're not trying to implement something like a debugger,
then I'd give you the following advice.

In general, a function is not supposed to behave differently depending
on who called it. Instead, you would vary the behaviour of the function
according to the data that it is operating on. You might do this by
examining the arguments, or by using "generic functions" and writing
different DEFMETHODS that use the same function name but operate on
different kinds of data. You could design complex data-driven control
structures this way.

Can you give some more information about the problem you're trying to solve?


Coby Beck

unread,
Jan 17, 2000, 3:00:00 AM1/17/00
to

Christopher C Stacy <cst...@world.std.com> wrote in message
news:x8lya9o...@world.std.com...

> "Coby Beck" <cb...@mercury.bc.ca> writes:
> > I s there a function that will programmatically return the name of the
> > function definition in which it is called? ie:
>
> There isn't a function in Common Lisp that will tell you who the
> calling function is up the stack. Individual implementations might
> have an internal function that does something like that, and they
> might document it. But it would by no means be normal to use such
> a function. Rather, it would be intended for use by things like
> the debugger.
>
> [snip]

> Can you give some more information about the problem you're trying to
solve?
>

It is intended for debugging purposes, something to be inserted and later
removed.

I guess the original thought was along the lines of replacing stuff like

(when (y-or-n-p "Break in hard-coded-function-name")
(break))

with
(break? (magic-function))

where break? might be defined as
(defun break? (function)
(when (y-or-n-p "Break in ~A" function)
(break))

Admittedly not a big deal in this example, but it got me curious. I wrote
some utilities I am very happy with that let me trap and bind local
variables so that on breaking i can manipulate them and test code line by
line. Perhaps there is a way with Allegro's debugger to bind variable
values? So far I have only been able to inspect.

I know of using +, ++, +++ and *, **, *** and there were others I believe to
return the previously evaluated forms and output etc. so i thought maybe
there were some other clever gadgets in the repertoire....


Coby

Erik Naggum

unread,
Jan 18, 2000, 3:00:00 AM1/18/00
to
* "Coby Beck" <cb...@mercury.bc.ca>

| Admittedly not a big deal in this example, but it got me curious.

I suggest reading the manual on Allegro CL's TRACE top-level command. as
far as I understand your question, it does what you want, and much more.

debugging by inserting code is generally considered to be very intrusive
to the code in question, and even more unlikely to produce efficient
bug-hunting. consider ADVICE, TRACE, STEP, etc, instead. debugging in
Common Lisp and C are as different as the languages are.

#:Erik

Sashank Varma

unread,
Jan 18, 2000, 3:00:00 AM1/18/00
to
In article <948127...@NewsSIEVE.cs.bonn.edu>, "Coby Beck"
<cb...@mercury.bc.ca> wrote:

[snip]


>I s there a function that will programmatically return the name of the
>function definition in which it is called? ie:
>

>(defun foo()
> (format t "Hello, from inside of ~A" (magic-function)))
>
>>(foo)
>"Hello, from inside of FOO"

[snip]

how about something like the following?

? (defmacro magic-defun (name lambda-list . body)
`(defun ,name ,lambda-list
(flet ((magic-function ()
',name))
,@body)))
MAGIC-DEFUN
? (magic-defun foo ()


(format t "Hello, from inside of ~A" (magic-function)))

FOO
? (foo)


Hello, from inside of FOO

NIL
?

sashank

Barry Margolin

unread,
Jan 18, 2000, 3:00:00 AM1/18/00
to
In article <sashank-1801...@129.59.212.53>,

Sashank Varma <sas...@vuse.vanderbilt.edu> wrote:
>how about something like the following?
>
>? (defmacro magic-defun (name lambda-list . body)
> `(defun ,name ,lambda-list
> (flet ((magic-function ()
> ',name))
> ,@body)))
>MAGIC-DEFUN
>? (magic-defun foo ()
> (format t "Hello, from inside of ~A" (magic-function)))
>FOO
>? (foo)
>Hello, from inside of FOO
>NIL
>?

If you're going to do it like that, there's not much point in using a
function -- a variable will do just as well:

(defmacro magic-defun (name lambda-list &body body)
`(defun ,name ,lambda-list
(let ((*current-function* ',name))
,@body)))

(magic-defun foo ()
(format t "Hello, from inside of ~A" *current-function*))

--
Barry Margolin, bar...@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

Sashank Varma

unread,
Jan 18, 2000, 3:00:00 AM1/18/00
to
In article <cA1h4.12$XS6.411@burlma1-snr2>, Barry Margolin
<bar...@bbnplanet.com> wrote:

>In article <sashank-1801...@129.59.212.53>,
>Sashank Varma <sas...@vuse.vanderbilt.edu> wrote:
>>how about something like the following?
>>
>>? (defmacro magic-defun (name lambda-list . body)
>> `(defun ,name ,lambda-list
>> (flet ((magic-function ()
>> ',name))
>> ,@body)))

[snip]


>
>If you're going to do it like that, there's not much point in using a
>function -- a variable will do just as well:
>
>(defmacro magic-defun (name lambda-list &body body)
> `(defun ,name ,lambda-list
> (let ((*current-function* ',name))
> ,@body)))
>

[snip]

good point.

if *current-function* has been declared special as the asterisks
imply, then our solutions will differ in their scoping/shadowing
properties, right? (i'm asking because you know much more about
these kinds of interactions than i do.)

they can definitely differ if the magic-defuned function returns
a closure, e.g.:

? (defmacro magic-defun (name lambda-list &body body)
`(defun ,name ,lambda-list


(flet ((magic-function () ',name))
,@body)))
MAGIC-DEFUN

? (magic-defun foo ()
#'(lambda ()
(magic-function)))
FOO

? (funcall (foo))
FOO

? (defparameter *current-function* 'bar)
*CURRENT-FUNCTION*

? (defmacro magic-defun2 (name lambda-list &body body)


`(defun ,name ,lambda-list
(let ((*current-function* ',name))
,@body)))

MAGIC-DEFUN2

? (magic-defun2 foo2 ()
#'(lambda ()
*current-function*))
FOO2

? (funcall (foo2))
BAR

?

sashank

Erik Naggum

unread,
Jan 18, 2000, 3:00:00 AM1/18/00
to
* Sashank Varma

| how about something like the following?
|
| ? (defmacro magic-defun (name lambda-list . body)
| `(defun ,name ,lambda-list
| (flet ((magic-function ()
| ',name))
| ,@body)))

while it appears to solve a problem, it actually doesn't. the problem is
to know where you are in the code you are trying to figure out why is not
working as it should. the solution is a backtrace. the solution is to
read the manual and understand how Common Lisp differs from C in such a
way that debugging code in them differs also.

what would we do without C? we would have PASAL, BASI, OBOL, and Ommon Lisp.

#:Erik

Erik Naggum

unread,
Jan 18, 2000, 3:00:00 AM1/18/00
to
* sas...@vuse.vanderbilt.edu (Sashank Varma)

| they can definitely differ if the magic-defuned function returns
| a closure, e.g.:

this illustrates the incompleteness of the "solution". take a hint and
realize that when a "solution" causes more new problems than it solves,
it's time to garbage collect it and look for what _solves_ the problem.

all in all, this "what's my name" question about functions is entirely
bogus, and we're just improving the way we get lost, instead of trying to
find our way home. see the manual on debugging if you use Allegro CL.
I'm sure the other professional Common Lisps have similar debugging
capabilities. (the free Lisps are lacking in this department to an
extent that those who reject commercial software will never understand
until they overcome their rejection.)

the way we deal with "what's my name" in recursive functions is to use
FLET inside the function, call it with suitable arguments, and avoid the
entire overhead of calling through a symbol's function slot. this also
works well with anonymous functions. however, it's a lexical name, and
there's no guarantee that no other function will do the same, so there's
no point in externalizing the name -- in fact, the opposite is the point:
to avoid externalizing the name.

Allegro CL comes with sufficient documentation and source code for
regular licencees that you can easily figure out how to get the function
object of the current frame. in most cases, you can query the function
object for the symbol (actually, function name) to which it was bound at
some time in the past. you have no guarantee that you get back the same
function object if you ask for the FDEFINITION of that function name.

it seems I'm repeating myself, but you are debugging up the wrong tree.
learn to use the Common Lisp debugger, don't try to emulate the behavior
you have been forced to accept from some inferior language -- it will
make Common Lisp seem inferior because we don't solve problems that never
should have had a solution in the first place, and the cost of which
solution actually carries severe penalties on the language design.

#:Erik

Joe Marshall

unread,
Jan 18, 2000, 3:00:00 AM1/18/00
to

Barry Margolin <bar...@bbnplanet.com> wrote in message
news:cA1h4.12$XS6.411@burlma1-snr2...

>
> If you're going to do it like that, there's not much point in using a
> function -- a variable will do just as well:
>
> (defmacro magic-defun (name lambda-list &body body)
> `(defun ,name ,lambda-list
> (let ((*current-function* ',name))
> ,@body)))
>
> (magic-defun foo ()
> (format t "Hello, from inside of ~A" *current-function*))

If tail-recursion matters to you, this solution will cause some
difficulties.


Barry Margolin

unread,
Jan 19, 2000, 3:00:00 AM1/19/00
to
In article <pY5h4.24712$b01....@dfw-read.news.verio.net>,

Why? There's only one call, to FORMAT, and it's a tail call. In fact, the
version with (magic-function) is less tail recursive, because the call to
MAGIC-FUNCTION wasn't a tail call.

BTW, although I put *'s around the variable *current-function*, I didn't
really intend for it to be declared special. It just seemed appropriate
for a "magic" variable like to have a name that stands out, similarly to
special variables. It's a lexical variable, but doesn't actually appear
lexically anywhere in the definition of FOO.

Joe Marshall

unread,
Jan 20, 2000, 3:00:00 AM1/20/00
to
I was confused by the *'s around *current-function* and thought you had
meant it as a special variable. I should pay more attention.

There is, of course, no problem with tail-recursion if it is a lexical
variable.
(Although you *could* gc the `buried binding' if it were dynamic, and thus
get back tail recursion, I don't know of any systems that actually do this.)

~jrm

Barry Margolin <bar...@bbnplanet.com> wrote in message

news:3Krh4.84$XS6.1259@burlma1-snr2...

Reply all
Reply to author
Forward
0 new messages