is there a way to determine if a function was called direct in the toploop (listener) or was called from another function?
I want to control what the function returns; say e.g. if called from the toploop (listener) it should return 'foo, if called from another function it should return 'bar.
st000...@hrzpub.tu-darmstadt.de (Federico Hernandez-Pueschel) writes: > is there a way to determine if a function was called direct in the toploop > (listener) or was called from another function?
No, not really. And there are philosophical problems with assuming there is a meaning to the concept of "toploop" since if Lisp is your language all the way down to the microcode (e.g., as on a Lisp machine) there is no real "top". There is just program on top of program on top of program on top of ...
Also, making it return something different at toplevel than in other places makes debugging REALLY hard in some cases.
> I want to control what the function returns; say e.g. if called from the > toploop (listener) it should return 'foo, if called from another function > it should return 'bar.
The wisdom of the ages is that at this point I should ask this question:
What are you REALLY trying to do?
(Usually when people ask odd little questions like this, they are trying to accomplish something utterly different and if one can get at that real purpose one can bypass the strange question altogether.)
> > I want to control what the function returns; say e.g. if called from the > > toploop (listener) it should return 'foo, if called from another function > > it should return 'bar.
> The wisdom of the ages is that at this point I should ask this question:
> What are you REALLY trying to do?
Maybe Federico wants to achieve a concept similar to Emacs' "interactive" function-calling. For instance, a function may behave differently when called via
(function ARGS ...)
than when you type:
M-x function
However, in Emacs, this difference does not exist on the Lisp level, because typing `M-x function' is equivalent to evaluating:
(call-interactively 'function ARGS ...)
where ARGS are divined from the function's interactive specs. In an interactively called function, `interactivep' will return non-nil.
Judging on experience from Emacs, there *is* use in distinguishing whether a function has been called interactively or noninteractively, but checking whether it has been evaluated from the listener definitely sounds like the wrong thing to do.
-- Hrvoje Niksic <hnik...@srce.hr> | Student at FER Zagreb, Croatia --------------------------------+-------------------------------- Then... his face does a complete change of expression. It goes from a "Vengeance is mine" expression, to a "What the fuck" blank look.
On 11 Dec 1997 21:35:32 +0100, Hrvoje Niksic <hnik...@srce.hr> wrote:
>Maybe Federico wants to achieve a concept similar to Emacs' >"interactive" function-calling. For instance, a function may behave >differently when called via
Something like that, yes.
>Judging on experience from Emacs, there *is* use in distinguishing >whether a function has been called interactively or noninteractively,
I can second that.
>but checking whether it has been evaluated from the listener >definitely sounds like the wrong thing to do.
What would be the best way to obtain a similar functionality?
Hrvoje Niksic <hnik...@srce.hr> writes: > However, in Emacs, this difference does not exist on the Lisp level, > because typing `M-x function' is equivalent to evaluating:
> (call-interactively 'function ARGS ...)
I agree one could impose a structurally different interface on things and solve the problem that way. Symbolics Genera did a similar thing with the command loop by allowing one to define new "commands" (with command-line syntax, rather than function calling syntax).
Looking back at the history, it seems surprising to me that there's not a way to customize the reader and printer function in CL since I think some implementations offer this option and it would have been an obvious thing to have standardized once-upon-a-time. More recently, standards work has moved slightly away from specifying too much detail of the interface, so it's less surprising that we haven't repaired the problem.
And then entering a context that customized any of the reader, evaluator, or printer for top-level.
I got private mail in which Federico said that computationally it would suffice to put a (view-top-level xxx) wrapper around his outermost call but that it was effectively tedious. An alternative would be a custom evaluator or printer which knew to watch for various xxx's and put the wrapper around automatically. I guess that's my best suggestion.
I could also suggest something like changing the problem from "toplevel" to "outermost" which is easier to compute. e.g.,
But if (foo (foo..)...) happens then you have the problem that the arg evaluation thinks it's at top level and returns a wrapped item that becomes an arg to FOO. The same would happen with mutually recursive functions. e.g., I "naively" tried:
(my-define foo (a b) (+ a b)) (my-define bar (a b) (- a b))
and did
(foo 1 2) => (wrapped 3) ;so far so good (bar (foo 1 2) (foo 2 3)) Error: In - of ((WRAPPED 3) (WRAPPED 5)) arguments should be of type NUMBER.
Oops. (I thought about removing the above example once I discovered it buggy but I thought it might comfort some people to watch me screw up... nobody's perfect, after all.) To repair this we might make these be more special-form-like, which eliminates the possibility of accessing #'foo (which works only for functions and not for macros). That means you can't apply, funcall, or map functions defined in this way.
So there are many ways you can do it, but basically SOMEBODY somewhere has to be responsible for putting the wrapper on because there is nothing that is busy noticing whether you're at top-level.
How about using the variable named "-", which ANSI defines as follows: The value of - is the form that is currently being evaluated by the Lisp read-eval-print loop.
Simplistically, one might define a function with &rest args, and then check that the car of "-" was the correct function, and the cdr was equal to the list of actual arguments.
I think a better idea would be to define the utility in question as a macro with an &whole argument, and then check that the this form is EQ to -. This assumes that EVAL never gratuitously copies the form being evaluated, and possibly other details that in theory are implementation dependent, but which I suspect don't vary much in practice.
> On 11 Dec 1997 21:35:32 +0100, Hrvoje Niksic <hnik...@srce.hr> wrote: > >Maybe Federico wants to achieve a concept similar to Emacs' > >"interactive" function-calling. For instance, a function may behave > >differently when called via > Something like that, yes.
> >Judging on experience from Emacs, there *is* use in distinguishing > >whether a function has been called interactively or noninteractively, > I can second that.
> >but checking whether it has been evaluated from the listener > >definitely sounds like the wrong thing to do. > What would be the best way to obtain a similar functionality?
Discussion subject changed to "Standardized, customizable REPL (was Re: Function called from the Listener or from another function)" by Howard R. Stearns
IMHO, specifying the details of the Read-Eval-Print-Loop is too confining for a language standard, but I DO think it would be nice to have a reference implementation which people can more-or-less count on.
I've often thought that it ought to be possible to define a subset of CLIM that covers presentations, command tables, and application frames -- none of which would have anything to do with graphics, sheets, media, ports, output recording, etc.
Given this, it would be nice if there were a reference implementation of a repl application frame and of invoke-debugger that used this frame. This could then be CLOS customized to define specialized application top-levels, debuggers, inspectors, steppers, etc.
Is this a dumb idea? Has anyone pursued this? How close was Genera to this? Maybe the free-clim people might want to start with this?
Kent M Pitman wrote: > ... > I agree one could impose a structurally different interface on things > and solve the problem that way. Symbolics Genera did a similar thing > with the command loop by allowing one to define new "commands" (with > command-line syntax, rather than function calling syntax).
> Looking back at the history, it seems surprising to me that there's > not a way to customize the reader and printer function in CL since I > think some implementations offer this option and it would have been an > obvious thing to have standardized once-upon-a-time. More recently, > standards work has moved slightly away from specifying too much detail > of the interface, so it's less surprising that we haven't repaired the > problem.
> How about using the variable named "-", which ANSI defines as follows: > The value of - is the form that is currently being evaluated by the > Lisp read-eval-print loop.
Oh how I dreaded someone raising this. It's a truly bad idea for "-" to be used because there is no guarantee that a function will be called from within a read eval print loop at all. For example, if you spawn a function into a new process of its own, it will not have "-" bound because there will be no human to type there. (perhaps the process is intended to start such a loop, but then it will do the bindings itself--they don't come pre-done).
Further, doesn't deal with what happens in (foo (bar ..)). Is bar being called from top level? It can't be determined lexically. Consider: (defun baz (a b) (bar a b)) In this case, - will contain (foo (baz x y)) and only by re-evaluating (baz ...) or by doing lots of code-introspection (halting problem alert) can you find out if bar gets involved. And you also have to worry about re-macorexpansions. What about (defmacro phu (&rest args) `(foo ,@args)) and - = (phu 1 2) The problems go on and on if you use -. As I say, I used to use it myself a lot in the Maclisp days and it always led to heartache.
-, *, **, ***, +, ++, +++, /, //, and /// as variables are only correctly used by a human being typing interactively or by programmatic Lisp teaching programs trying to heuristically suggest corrections. (Just my opinion.)
Even if you can find an expression like ((lambda (x) (format t "~&~S => ~S~%" (cadr -) x)) (* 3 4)) that yields cool output, you have to notice it won't work in a file load or editor buffer evaluation. It's best if you have such a need to do a structural thing like (let ((form '(* 3 4))) (format t "~&~S => ~S~%" form (eval form))) or if you can't use eval for some reason, (format t "~&~S => ~S~%" '#1=(* 3 4) #1#) which is at least reliable in all the Lisp evaluators and compilers.
* Hrvoje Niksic wrote: > Judging on experience from Emacs, there *is* use in distinguishing > whether a function has been called interactively or noninteractively, > but checking whether it has been evaluated from the listener > definitely sounds like the wrong thing to do.
Actually I found that kind of thing quite useful at points. I wrote a little debugger for elk (a scheme dialect) which checked whether the error was happening from an interactive toploop, and if so how far down the stack it was. If it was very close to the top of the stack it would just print a message and return to the toploop, rather than crank up the debugger. The idea was that if I typed: `(car 1)' I just wanted it to print a message and stop, but if I said `(run-huge-program-wich-has-a-bug-way-down-inside-somewhere)' I wanted the debugger (except I didn't if it was running from a script). I think the xerox D machines did something similar, which is where I got the idea for my elk debugger from.
So both things are useful to know I think. OTOH I don't think that CL should standardise such a thing (even a stack-depth test between two points would make all sorts of constraining assumptions).
In article <34948420.53529...@news.tu-darmstadt.de>,
Federico Hernandez-Pueschel <st000...@hrzpub.tu-darmstadt.de> wrote: >What would be the best way to obtain a similar functionality?
The simplest way is to define two functions, one intended to be called by hand from the listener, and another intended for use in programs. The first one would probably call the second one to do most of its work.
For instance, one reason you might want to have a function behave differently when called interactively is to prevent it from returning a value which is likely to be a huge data structure. So you might define:
(defun foo-internal (...) ...)
(defun foo (...) (foo-internal ...) nil)
The nice thing about this is that you can still call foo-internal from the listener if you want (e.g. when debugging, you might want to see that huge data structure).
I can recall many times typing (progn (...) nil) just so I wouldn't have to see the return value of the function I was testing (especially when the function's purpose is to print something, so the return value is the same thing it just printed).
-- Barry Margolin, bar...@bbnplanet.com GTE Internetworking, Powered by BBN, Cambridge, MA Support the anti-spam movement; see <http://www.cauce.org/> Please don't send technical questions directly to me, post them to newsgroups.
> On 11 Dec 1997 21:35:32 +0100, Hrvoje Niksic <hnik...@srce.hr> wrote: > >Maybe Federico wants to achieve a concept similar to Emacs' > >"interactive" function-calling. For instance, a function may behave > >differently when called via > Something like that, yes.
> >Judging on experience from Emacs, there *is* use in distinguishing > >whether a function has been called interactively or noninteractively, > I can second that.
> >but checking whether it has been evaluated from the listener > >definitely sounds like the wrong thing to do. > What would be the best way to obtain a similar functionality?
> Greetings
> Federico
Hmmm. I'm not advocating general use of "-" in programs, but in a specific situation, described above. My reading of the above is that the programmer wishes to know whether a single function was called interactively from top level. That is, whether the form entered at top level was a cons beginning with some symbol. (Maybe I've misunderstood?)
It is my understanding that this is PRECISELY what cl:- is defined to be bound to, where neither I nor the standard have bothered to define what is meant by the "top level". If the implemenation provides some definition of a top level for which cl:- is not bound to the current form being evaluated by that top level, then the implementation is out of compliance.
Being more speculative, and increasinly unsure of my ground, imagine that an implementation defined a mechanism by which one could invoke multiple top level REPLs in different threads. (See my separate speculations in the "Standardized, customizable REPL" thread.) My reading of the spec is that as long as this mechanism was defined to provide a "top level" listener, the implementation would be required to ensure that within the same thread in which the customized REPL was running, cl:- would have to be bound to the form being evaluated by it. (I'm assuming one REPL per thread.)
Conversely, if an implementation only provides one REPL and no mechanism for defining new ones, then cl:- must be bound in all threads.
The middle ground, where there is no REPL in the current thread, is certainly "undefined". I suppose on might want per-thread globals that can inherit from other threads, but that's another story.
Anyway, remember that the problem is framed by analogy to emacs, where I believe calling something at the top level means M-x function-name arg1 arg2 ... and not M-x some-other-function function-name arg1 arg2 ... end-of-argument-marker-for-function-name arg-2-for-some-other-function ....
Therefore, I think we can define (bar 1) to not be considered called at top-level when cl:- is (foo (bar 1) 4).
> > How about using the variable named "-", which ANSI defines as follows: > > The value of - is the form that is currently being evaluated by the > > Lisp read-eval-print loop.
> Oh how I dreaded someone raising this. It's a truly bad idea for "-" to > be used because there is no guarantee that a function will be called from > within a read eval print loop at all. For example, if you spawn a function > into a new process of its own, it will not have "-" bound because there will > be no human to type there. (perhaps the process is intended to start > such a loop, but then it will do the bindings itself--they don't come > pre-done).
> Further, doesn't deal with what happens in (foo (bar ..)). Is bar being > called from top level? It can't be determined lexically. Consider: > (defun baz (a b) (bar a b)) > In this case, - will contain (foo (baz x y)) and only by re-evaluating > (baz ...) or by doing lots of code-introspection (halting problem alert) > can you find out if bar gets involved. And you also have to worry about > re-macorexpansions. What about > (defmacro phu (&rest args) `(foo ,@args)) > and - = (phu 1 2) > The problems go on and on if you use -. As I say, I used to use it > myself a lot in the Maclisp days and it always led to heartache.
> -, *, **, ***, +, ++, +++, /, //, and /// as variables are only > correctly used by a human being typing interactively or by programmatic > Lisp teaching programs trying to heuristically suggest corrections. > (Just my opinion.)
> Even if you can find an expression like > ((lambda (x) (format t "~&~S => ~S~%" (cadr -) x)) (* 3 4)) > that yields cool output, you have to notice it won't work in a file load > or editor buffer evaluation. It's best if you have such a need to do > a structural thing like > (let ((form '(* 3 4))) > (format t "~&~S => ~S~%" form (eval form))) > or if you can't use eval for some reason, > (format t "~&~S => ~S~%" '#1=(* 3 4) #1#) > which is at least reliable in all the Lisp evaluators and compilers.
* Hrvoje Niksic | Judging on experience from Emacs, there *is* use in distinguishing | whether a function has been called interactively or noninteractively, | but checking whether it has been evaluated from the listener | definitely sounds like the wrong thing to do.
Emacs exports its Lisp call stack. `interactivep' actually walks up the call stack and looks for a call frame with `call-interactively' in it, skipping only a few known call frames on the way. if it finds it, the function is deemed "interactive".
if your Lisp has a debugger that can print backtraces, it has a way to locate call frames. if you can also use it, you can do the same job as Emacs' `interactive-p': look for a particular function you expect to mean "interactive" in the backtrace.
there are many other ways to distinguish between an interactive call and a normal call, but they generally require changes in the caller. this is most easily solved by writing one's own top-level loop, which is not all that hard.
in any case, I miss the ability in Common Lisp to obtain the function object corresponding to the running function. in Emacs, this is (almost) achievable through (backtrace-frame 0).
#\Erik -- If you think this year is number 97, | Help fight MULE in GNU Emacs 20! _you_ are not "Year 2000 Compliant". | http://sourcery.naggum.no/emacs/
Barry Margolin <bar...@bbnplanet.com> writes: > I can recall many times typing (progn (...) nil) just so I wouldn't have to > see the return value of the function I was testing.
Heh. I do (setq foo (...) bar nil) a lot for the same reason.
> It is my understanding that this is PRECISELY what cl:- is defined to be > bound to, where neither I nor the standard have bothered to define what > is meant by the "top level". If the implemenation provides some > definition of a top level for which cl:- is not bound to the current > form being evaluated by that top level, then the implementation is out > of compliance.
Nope. This is too strong, I think. I'm extremely conservative about saying that an implementation is non-compliant. Again, this goes back to the first meting of X3J13 which I recently expounded about under another thread in which someone from then-X3 (it has another name now, btw, it's formally called NCITS and pronounced "insights") spoke to us about how lawsuits have happened when "experts" have accused language implementations that purport to conform of being non-conforming. It is wiser, we were counselled, to give as broad a latitude as possible in the case of an ambiguity, and I certainly see lots of reason for latitude in this case.
Nowhere that I know of does it say that a read eval print loop is required by Lisp. Various things are forced of the read eval print loop, but a delivery-only Lisp would be a commercially viable product and it's really up to the consumer, I think, to decide if that's ok. I think that was the intent of the committee anyway, even if it's not spelled out.
Further, a compliant implementation (which includes most implementations I'm familiar with) is permitted to launch processes with no REPL. These are not required to bind - to any particular value. (The spec says it's got a value, but it doesn't say what it is, and in my experience it's usually NIL.) I'd actually advise anyone using the variable named "-" in a program to boundp test it first just to be sure, although I'd advise any implementor to globally assign it to NIL just to avoid the need for that. That kind of split advice is common in cases of lack of specificity.
BTW: Note that this is implied in discussion of the ABORT restart, which implies that there might be non-interactive contexts where there is no command level. This supports my belief that the committee did believe in non-interactive lisps.
I'll queue this issue on my private list of things to be clarified if/when a next round standard comes up for discussion.
> Being more speculative, and increasinly unsure of my ground, imagine > that an implementation defined a mechanism by which one could invoke > multiple top level REPLs in different threads. (See my separate > speculations in the "Standardized, customizable REPL" thread.) My > reading of the spec is that as long as this mechanism was defined to > provide a "top level" listener, the implementation would be required to > ensure that within the same thread in which the customized REPL was > running, cl:- would have to be bound to the form being evaluated by it. > (I'm assuming one REPL per thread.)
Yes. A thread that runs a REPL should bind -, but again: a thread need not run a REPL.
> Conversely, if an implementation only provides one REPL and no mechanism > for defining new ones, then cl:- must be bound in all threads.
Probably. I'd encourage implementors to think this way. But I'd also encourage programmers to program defensively. :-)
> The middle ground, where there is no REPL in the current thread, is > certainly "undefined". I suppose on might want per-thread globals that > can inherit from other threads, but that's another story.
Well, the spec says the value is "implementation-dependent". My personal hope is that people would read this to mean "there is a value and that value is implementation-dependent". As a matter of practice, we would have used the word "undefined" rather than "implementation-dependent" had we meant to imply otherwise. But I agree that leaving wriggle room is good and so while I'm not content to agree that it is `certainly "undefined"' I'm willing to agree that it is `effectively "undefined"' :-)
> Anyway, remember that the problem is framed by analogy to emacs, where I > believe calling something at the top level means > M-x function-name arg1 arg2 ... > and not > M-x some-other-function function-name arg1 arg2 ... > end-of-argument-marker-for-function-name arg-2-for-some-other-function > ....
> Therefore, I think we can define (bar 1) to not be considered called at > top-level when cl:- is (foo (bar 1) 4).
You can indeed. Absolutely. But figuring out how to implement that is tough. My simple try using a *outermost* variable got confused because both FOO and BAR are called as if side-by-side, not nested. If you do a conversion to continuation passing sytle, it's easier to see: ((lambda (x) (foo x 4)) (bar 1))
Now it's easier to see that (foo x 4) and (bar 1) are really equals in top-ness. And it might even be argued that the bar call is more outer than the foo call. What is correct is not a matter for philosophers (who will argue forever) but Federico (who presumably has a specific intent in mind).
On Fri, 12 Dec 1997 06:47:20 GMT, Kent M Pitman <pit...@world.std.com> wrote:
> An alternative would be a custom evaluator or printer which knew > to watch for various xxx's and put the wrapper around automatically.
Interesting idea.
One could do the following (not optimized): The custom evaluator checks the function to evaluate against a table which contains all functions to check and their wrapper functions. If the cust-eval finds the function, it retrievs the the wrapper function and applies it to the original function. A new written function that needs a wrapper could insert itself and the wrapper function into the table.
> (I thought about removing the above example once I discovered > it buggy but I thought it might comfort some people to watch me screw > up... nobody's perfect, after all.)
:-))
>You're on your own from here.
I am thinking of doing some work on your first idea.
On Fri, 12 Dec 1997 16:57:11 -0600, "Howard R. Stearns" <how...@elwood.com> wrote:
>Hmmm. I'm not advocating general use of "-" in programs, but in a >specific situation, described above. My reading of the above is that >the programmer wishes to know whether a single function was called >interactively from top level. That is, whether the form entered at top >level was a cons beginning with some symbol. (Maybe I've >misunderstood?)
No, you are quite right. The programs will be invoked from a REPL. The output of some functions are, as they will be input for other functions, not really readable for humans. But for didactic reasons I (or the user) should also be able to read this output when we invoke this function from the toplevel.
So it can be guaranteed, that there is a REPL. And it seems interesting to use cl:-. I really forgot about that variable, thinking of another variable or function to detect a call from the toploop.
Some quick tests here showed that using cl:- will work and be sufficient. So for the time being I will just check the car of cl:- against the name of the function and decide upon this check what to return.
Later on I will follow Kent's idea of the custom evaluator. It would be nice to solve "the maintenance problem" of such a cust-eval during the development phase of a project.
On Fri, 12 Dec 1997 21:48:18 GMT, Barry Margolin <bar...@bbnplanet.com> wrote:
>The simplest way is to define two functions, one intended to be called by >hand from the listener, and another intended for use in programs. The >first one would probably call the second one to do most of its work.
On some occasions I am allready doing this. But then I have two functions which do the "same". I wanted to avoid this with putting some "intelligence" into the function and let the function decide what to return.
>I can recall many times typing (progn (...) nil) just so I wouldn't have to >see the return value of the function I was testing (especially when the >function's purpose is to print something, so the return value is the same >thing it just printed).