betz@decvax.UUCP (David Betz) (11/16/83)
Does anyone know the reasoning behind why LISP keeps a separate function value cell for each atom? Why isn't the normal value cell used to store function values? If the normal value cell were used, the evaluator could just 'eval' the first element of a form in order to find the function being applied. I used this approach in my XLISP language. The reason that I needed to 'eval' the first element of a form was that I wanted to be able to handle normal function application and object oriented message passing in a form. For instance: (fun arg1 arg2) ; call function 'fun' with arguments 'arg1' ; and 'arg2' (obj msg arg1 arg2) ; send 'obj' the message 'msg' with arguments ; 'arg1' and 'arg2' The problem comes when the object in a message is itself an expression: ((obj1 msg1 arg1) msg2 arg2) ; first send the 'obj1' the message 'msg1' ; with argument 'arg1'. ; then take the value of that expression ; and send it the message 'msg2' with ; argument 'arg2' If 'eval' doesn't evaluate the first element of a form, the (obj1 msg1 arg1) message is never evaluated. I solved this problem by storing the function value of an atom in the same place as the normal value. Then whenever I evaluate a form, I first evaluate the first element to find out if it is a function or an object. If it is a function, I do a normal function call. If it is an object, I send the object a message. What I am wondering is whether I have violated a basic principle of LISP in changing the evaluator to work in this way. Why is it important to keep function values separate from normal values? Is this convention just historical? If the answer to this question is obvious, please forgive my ignorance. Thanks, David Betz decvax!betz
shebs@utah-cs.UUCP (Stanley Shebs) (11/16/83)
It's debatable whether the function cell should be the same as the value cell. As I understand it, at one time PSL made them the same, then it was decided to separate the two, to "avoid function-variable naming clashes" (quoting the manual). I fully agree with that reasoning - the set of Lisp reserved words (the oblist) is sufficiently large (1000-2000) that anything to reduce the possibility of conflicts is a good idea... stan the l.h. utah-cs!shebs
carr@utah-cs.UUCP (Harold Carr) (11/16/83)
A discussion on the function cell took place on lisp-forum@MIT-MC on the arpa net last summer. Here are the words from the people who did and are doing the original work. Hope this message is not too long. I found the discussion interesting and thought it would be useful to pass it along to everyone here. Harold Carr (CARR@UTAH-20.ARPA | utah-cs!carr) >Date: 23 Aug 1983 1135-MDT >From: Julian Padget <PADGET@UTAH-20> >Subject: function cells I am doing a little bit of historical digging on LISP, and I would like to know who claims responsibility for the invention of the function cell which is common to so many LISP implementations. Further I would be interested to hear a justification for both its invention and retention. --Julian Padget (Padget@Utah-20). ------- >Date: Tue, 23 Aug 83 14:13 PDT >From: Deutsch.PA@PARC-MAXC.ARPA >Subject: Re: function cells >In-reply-to: "PADGET@UTAH-20.ARPA's message of 23 Aug 83 11:35 MDT" Lisp 1.5 stored function definitions on the property list. To my knowledge, the first Lisp that used an independent function cell was the PDP-1 implementation of BBN-Lisp, the precursor of Interlisp. Dan Bobrow may be able to confirm or add details. This would have been around 1965. He and I were the principal architects of this system; I would trust his word about who invented what. You may find other interesting historical information in the Information International Inc. Lisp system book, edited by Edmund C. Berkeley and also published sometime around 1965. It doesn't describe BBN-Lisp, but it describes some other systems, and one of them may have function cells -- I don't really remember. I don't know what alternatives you want a justification with respect to. The changeover from property list representation was primarily for efficiency. The distinction between "function context" and "variable context" for interpreting names was a bad idea inherited from Lisp 1.5: it was retained for a very long time because doing free variable lookups for every function name (which are normally only bound at the top level) would have been atrociously slow. It was only with the invention of shallow binding that people started to look seriously at re-merging function and variable binding. >Date: Tue, 30 Aug 83 13:54 PDT >From: Bobrow.PA@PARC-MAXC.ARPA >Subject: Re: function cells >In-reply-to: "Deutsch's message of Tue, 23 Aug 83 14:13 PDT" I must admit that it was my idea of having separate function cells, value cells, pname cells, and property lists for Lisp atoms in BBN-Lisp. I am a believer in separating out mechanisms when there are distinct differences in function. I think lookup of functions is semantically different than lookup of variables. The time scale for which bindings are applicable for variables and fn definitions are applicable are quite different different in the usual case. >Date: 30 August 1983 23:58 EDT >From: George J. Carrette <GJC @ MIT-MC> >Subject: Function cells. I would credit JONL with introducing what is effectively the function-cell functionality to Maclisp. Even though the internals of the function calling mechanism in maclisp uses various properties, EXPR, FEXPR, LSUBR, SUBR, FSUBR, and also various function cells with the UUOLINK mechanism, the user only need be aware of the existence of DEFUN. Here is some old lisp mail on the topic: 3/1/69 JONL THE CURRENT VERSION OF LISP, "LISP 102", HAS THE FOLLOWING AS-YET UNDOCUMENTED FEATURES: 1)"DEFUN" IS AN FSUBR USED TO DEFINE FUNCTIONS. EXAMPLES ARE (DEFUN ONECONS (X) (CONS 1 X)) WHICH IS EQUIVALENT TO (DEFPROP ONECONS (LAMBDA (X) (CONS 1 X) EXPR) THE NOVEL FEATURE OF "DEFUN" IS THAT ONE NEED NOT BE SO CONCERNED WITH BALANCING PARENTHESES AT THE VERY END OF THE FUNCTION DEFINITION. ALSO, THE "LAMBDA" NEED NOT BE DIRECTLY INSERTED. Of course, the time this note was written none of the hairier specialized calling mechanisms had been added to maclisp. -gjc >Date: Thu, 1 Sep 1983 07:37 EDT >From: TIM@MIT-OZ >Subject: Function cells >In-reply-to: Msg of 30 Aug 1983 16:54-EDT from Bobrow.PA at PARC-MAXC.ARPA For the "usual case" it is perfectly reasonable to have separate function and value cells--I make use of that feature all the time. But the situation changes when you start to pass functions around in value cells. The awkward convention of specifying a function call by (FUNCALL fun arg1 arg2 ...) ;where the function is found in the ;value cell of FUN rather than (fun arg1 arg2 ...) ;in the usual case is perpetuated by having both a function cell and a value cell. In languages which do not adopt this convention (such as Gerry Sussman and Guy Steele's Scheme) it is possible to use the latter form in every case, even when FUN has been passed as an argument. Thus (define (foo fn a b) ;(The slight difference in the syntax (fn (* 2 a) b)) ;of FOO's function spec is incidental) replaces (defun foo (fn a b) (funcall fn (* 2 a) b)) I realize that the deep binding scheme in early Lisp implementations made it necessary to have a separate mechanism for fast function lookup, and that the namespace limitation of dynamic scoping makes having a function context and a variable context handy, but I do not think that the function/value dichotomy should continue into the lexically scoped Common Lisp. In the case where a variable contains a function (in its value cell) I see little semantic distinction between the lookup of variables and functions. In this respect, I fail to see your point about "separating out mechanisms." I see it justifiable only for efficiency reasons and for coping with a limited namespace. Tim McNerney >Date: Thu, 1 Sep 83 14:30 PDT >From: Bobrow.PA@PARC-MAXC.ARPA >Subject: Re: Function cells >In-reply-to: <[MIT-OZ].TIM. 1-Sep-83 07:37:32> Tim, There is a difference in meaning between: (fun x y) and (FUNCALL fun x y). In the former case, one expects the meaning of fun to be independent of the context of the call. In the latter, to be dependent of parameters passed in to the environment. One can take the point of view that one doesn't want to distinguish these cases, but I maintain that the code is clearer when you do make the distinction for the call. Similarly, I have seen proposals for doing object oriented programming by having the function name evaluated in the context of the first argument to the function (which would in fact be a closure on some functions and variables). I object to that as well. So for me the question is not about efficiency and limitation of name space, but of what distinctions you want to make apparent at a call. danny bobrow >Date: Thursday, 1 September 1983, 15:35-PDT >From: Eric Benson <BENSON at SPA-Nimbus> >Subject: Re: Function cells By this reasoning you must object to the Common Lisp special forms LABELS and FLET, which define lexically scoped functions. With the inclusion of these, function name evaluation is no longer independent of context. It is only dependent on the static context, however; there is no dynamic binding of function names in Common Lisp. Is it only dependence on dynamic context you object to, or dependence on any context? >Date: Thu, 1 Sep 83 16:19 PDT >From: Deutsch.PA@PARC-MAXC.ARPA >Subject: Re: Function cells >In-reply-to: "Bobrow's message of Thu, 1 Sep 83 14:30 PDT" Danny, I have to side with the Common Lisp / T people on this one. Just because most (but not all) function invocations use names that are bound in a global, flat name space (which all modern Lisp systems are finding ways to enrich), and most (but not all) variables are bound more locally (in this lexical scope? in a dynamically enclosing but far-from-apparent scope? in an enclosing lexical scope?), is not enough of a reason for introducing a mechanism that adds complexity all over the system. T takes the viewpoint that all identifiers are on a par. The compiler is able to take advantage of pragmatic information about things being constant or not dynamically rebound, regardless of whether they are functions or variables. I imagine Common Lisp is the same. Function cells seemed like a good idea at the time, just like GLOBALVARS. I think they were both pragmatic successes and semantic mistakes. >Date: 1 Sep 1983 1746-MDT >From: Julian Padget <PADGET@UTAH-20> >Subject: Re: Function cells As an aside to the main discussion, I do not condone the use of both the function and the value cell as a programming style, I am also doubtful about Tim's appellation of this as a feature. I should also remark that there are some 'real' LISPs that only provide one location for keeping a value associated with an id (ie no function cell), in particular Cambridge LISP. I would vote with Tim to remove this dichotomy which is being continued in Common LISP, for reasons which are given in more detail below. However I strongly suspect that the main reason for its retention in CL is not for aesthetic but political motives - how else is MACSYMA going to run under CL, the coding style therein uses this 'feature' quite a lot, and rewriting all the affected parts is not an overnight job. I maintain that a function IS a value, and the distinction between value and function is erroneous. Although no-one would seriously regard LISP as a faithful implementation of the semantics of lambda calculus, it is not unreasonable to pay lip service to its (our??) heritage. With respect to the question of clarity: there is a problem with the handling of anonymous functions (as in say the MAP functions), and in the case of high order functions. Although this example may seem somewhat contrived, it is relevant. R-Sum and I-sum define functions to do a curried summation (I provide both for a little variety): (De R-Sum (a0) (Function (Lambda (ai) (Cond ((Zerop ai) a0) (t (R-Sum (Plus a0 ai))))))) alternatively: (De I-Sum (a0) (Prog (fn) (Return (SetQ fn (Function (Lambda (ai) (Cond ((Zerop ai) a0) (t (SetQ a0 (Plus a0 ai)))) fn)))))) now using these in a single cell system gives rise to the following expression: (((((I-sum 1) 2) 3) 4) 0) if FUNCALL must be used this becomes: (FunCall (FunCall (FunCall (FunCall (I-sum 1) 2) 3) 4) 0) In addition to being a matter of style/personal taste, it is a question of consistency (as Peter Deutsch remarked), each element of a form is treated the same way - even assuming the first element is evaluated repeatedly until an object which can be applied is found, since that is simply a recursion in eval without passing the rest of the form downwards. --Julian Padget. ------- >Date: Thu, 1 Sep 83 18:11 PDT >From: Bobrow.PA@PARC-MAXC.ARPA >Subject: Re: Function cells >In-reply-to: "BENSON@SPA-Nimbus.ARPA's message of Thu, 1 Sep 83 15:35 PDT" I don't object to definitions which depend on context. I like to see uses which depend on such context dependent definitions distinguished from ones which don't. >Date: Sat, 3 Sep 1983 14:38 EDT >From: ZVONA@MIT-OZ >Subject: Function cells >In-reply-to: Msg of 1 Sep 1983 21:11-EDT from Bobrow.PA at PARC-MAXC.ARPA The "function spec" problem in Common Lisp is one that makes clear the advantages of treating "functions and values" uniformly. It is common to store functions as properties of symbols. This allows a clean implementation of data-directed dispatching: you write (funcall (get snabozzle 'quibbix) . args) in order to do a quibbix-type dispatch on the snabozzle. To support this, you want a clean way to write the functions that will be stored on the property list and to get them into the property list. In a lambda calculus system, you might write (put 'some-snabozzle 'quibbix (lambda ...)) but modern lisps have defun, which has a lot of useful syntax that you'd like to use in defining the dispatched-to functions. Maclisp provided the syntax (defun (some-snabozzle quibbix) arglist . body) which would effectively macroexpand into the same thing (and also hack defun-syntax and process declarations and so forth for you). This syntax had a number of problems; among them, especially, that besides the "function cell" and properties there are other places that you might want to store functions. Therefore, lisp machine lisp did an almost-upward-compatible extension to this in which the defun name (first subform) if a list would dispatch on the car of the list if possible. The car of the list could then be a keyword that would tell where to put the function. (defun (:property some-snabozzle quibbix) arglist . body) for example. These lists (such as (:property ...)) were called "function specs". The lisp machine provides for each function spec a set of things that can be done to it: you can define it, undefine it (make it unbound), get its definition, and so on. All this amounts to a fair amount of conceptual overhead (though to total amount of code to implement it fits in a few pages). It is no longer obvious just what it is that defun abstractly macroexpands into; it is doing some magic with the function specs behind your back. Moreover, it is often unclear in what contexts it is allowable to use a function spec. For example, beginners who are first introduced to function specs often try to write ((:property snabozzle quibbix) . args) or (funcall (:property snabozzle quibbix) . args) This suggests that perhaps what one ought to be writing is (defun (get 'some-snabozzle 'quibbix) arglist . body) because it is intuitively clearer if the defining and using forms have the same syntax. Moreover, this eliminates all the overhead of function specs. And then defun again has a clear macroexpansion: it is really just sugar for setf! That is, the defun above is really (setf (get 'some-snabozzle 'quibbix) (lambda arglist . body)) There is just one difficulty with this: what does (defun drofnats (self) (capitalize (string-reverse self))) macroexpand into? It ought to be (setf drofnats (lambda (self) (capitalize (string-reverse self)))) but that sets the value cell, not the function cell! This, finally, is the point: The elegant setf syntax for defun was abandoned for common lisp because it didn't "work" on symbols. The true story is that the uniform handling of functions as values is a self-consistent system, and function cells are a confused mess. *** *** *** *** It is worth mentioning that (function ...) is intimately tied up with the function cell lossage. Common lisp weirdly chose to implement lambda right, but to require a no-op #' in front of it. (Anyone who wants to win, of course, can define lambda as a macro that expands into #'(lambda ...). Takes all kinds.) *** *** *** *** Common lisp people: defun setf syntax seems like such a win that perhaps it could be salvaged by the following klduge (which seems better than function specs): defun has setf-syntax except on symbols. It uses the function cell with symbols. You can set the value cell of a symbol with (defun (symbol-value symbol) ...) >Date: Saturday, 3 September 1983, 21:06-EDT >From: Robert W. Kerns <RWK at SCRC> >Subject: Function cells >In-reply-to: <[MIT-OZ].ZVONA. 3-Sep-83 14:38:45> >Date: Sat, 3 Sep 1983 14:38 EDT >From: ZVONA@MIT-OZ The "function spec" problem in Common Lisp is one that makes clear the advantages of treating "functions and values" uniformly. It is common to store functions as properties of symbols. This allows a clean implementation of data-directed dispatching: you write (funcall (get snabozzle 'quibbix) . args) in order to do a quibbix-type dispatch on the snabozzle. To support this, you want a clean way to write the functions that will be stored on the property list and to get them into the property list. In a lambda calculus system, you might write (put 'some-snabozzle 'quibbix (lambda ...)) but modern lisps have defun, which has a lot of useful syntax that you'd like to use in defining the dispatched-to functions. Maclisp provided the syntax (defun (some-snabozzle quibbix) arglist . body) which would effectively macroexpand into the same thing (and also hack defun-syntax and process declarations and so forth for you). This syntax had a number of problems; among them, especially, that besides the "function cell" and properties there are other places that you might want to store functions. Therefore, lisp machine lisp did an almost-upward-compatible extension to this in which the defun name (first subform) if a list would dispatch on the car of the list if possible. The car of the list could then be a keyword that would tell where to put the function. (defun (:property some-snabozzle quibbix) arglist . body) for example. These lists (such as (:property ...)) were called "function specs". The lisp machine provides for each function spec a set of things that can be done to it: you can define it, undefine it (make it unbound), get its definition, and so on. All this amounts to a fair amount of conceptual overhead (though to total amount of code to implement it fits in a few pages). It is no longer obvious just what it is that defun abstractly macroexpands into; it is doing some magic with the function specs behind your back. Moreover, it is often unclear in what contexts it is allowable to use a function spec. For example, beginners who are first introduced to function specs often try to write ((:property snabozzle quibbix) . args) or (funcall (:property snabozzle quibbix) . args) This suggests that perhaps what one ought to be writing is (defun (get 'some-snabozzle 'quibbix) arglist . body) No, one should write (funcall #'(:property snaboozle quibbix) . args) just like one should write (funcall #'snaboozle . args) or (funcall #'(lambda (x) (+ x x)) . args). The non-uniformity here is that (funcall 'snaboozle . args) or (funcall '(lambda (x) (+ x x)) . args) will work at all. The only problem with writing ((:property snabozzle quibbix) . args) is that it is visually confusing. You can't argue that because ((:property snabozzle quibbix) . args) doesn't work that the idea of a function spec is inelegant! At most you can say that a piece of it that should work doesn't. because it is intuitively clearer if the defining and using forms have the same syntax. Moreover, this eliminates all the overhead of function specs. And then defun again has a clear macroexpansion: it is really just sugar for setf! Bullshit. DEFUN started out life as sugar for DEFPROP, not PUTPROP. The difference is that the compiler was then considered free to compile things defined with DEFPROP. In more modern times, the compiler is considered free to compile things "quoted" with FUNCTION rather than QUOTE. So... That is, the defun above is really (setf (get 'some-snabozzle 'quibbix) (lambda arglist . body)) There is just one difficulty with this: what does (defun drofnats (self) (capitalize (string-reverse self))) macroexpand into? It ought to be (setf drofnats (lambda (self) (capitalize (string-reverse self)))) but that sets the value cell, not the function cell! In the current scheme, (DEFUN FOO (X) (BAR X)) ==> (SETF #'FOO #'(LAMBDA (X) (BAR X))) (DEFUN (:PROPERTY FOO :FUN-PROP) (X) (BAR X)) ==> (SETF #'(:PROPERTY FOO :FUN-PROP) #'(LAMBDA (X) (BAR X))) This, finally, is the point: The elegant setf syntax for defun was abandoned for common lisp because it didn't "work" on symbols. The true story is that the uniform handling of functions as values is a self-consistent system, and function cells are a confused mess. That is indeed the problem with your scheme, it turns function cells into a confused mess. It also ignores every shred of consistancy in favor of your own internal confusion. Proof by Solipsism is not acceptable. *** *** *** *** It is worth mentioning that (function ...) is intimately tied up with the function cell lossage. Common lisp weirdly chose to implement lambda right, but to require a no-op #' in front of it. (Anyone who wants to win, of course, can define lambda as a macro that expands into #'(lambda ...). Takes all kinds.) You're right, it is connected. You can view (FUNCTION ...) as meaning "do what you do to the CAR of a combination to get the function to be performed". It doesn't buy you much to say that what you do with the FIRST of a form should be the same as what you do the the SECOND. It just isn't true after you get your hands on the function, especially in the case of macros. The distinction here is very much like the distinction between nouns and verbs in English. Frequently a word is both a noun and a verb, but the distinction is clear from context. For example, LIST is both a noun and a verb. I have seen many users of lisps without function cells SCREW THEMSELVES TO THE WALL by using something as a temporary variable that happens to also be a function name. LIST is the most common offender. (This is made worse by lisps which defaultly use dynamic scoping, but people also have screwed themselves doing (SETQ LIST (GET-ITEM-LIST 'FOO)) at top level). *** *** *** *** Common lisp people: defun setf syntax seems like such a win that perhaps it could be salvaged by the following klduge (which seems better than function specs): defun has setf-syntax except on symbols. It uses the function cell with symbols. You can set the value cell of a symbol with (defun (symbol-value symbol) ...) ARGH! This does nobody any favors. It is every bit as bad as you imagine distinguishing between functions and values is. This debate really annoys me, partly because not a single new thing has been said (with the exception of your SETF/DEFUN scheme, which I detest). Most of the people involved with Common Lisp have faced this issue and been thinking about it for 5 years or more. Most of the arguments against it are based on an unstated assumption that saying (FUNCALL X ...) is an unwanted complexity rather than a helpful clarification, or that the slight simplification of eliminating the function cell is worth sacraficing the clarity, or that the slight simplification of calling EVAL on the CAR of the form is worth anything at all. What I don't understand is why everybody goes on about the FUNCTION cell in favor of the VALUE cell. Why isn't anybody proposing we do away with the VALUE cell. The history of the VALUE cell in MacLisp *IS THE SAME AS THAT OF THE FUNCTION CELL*. I.e. they both used to simply be properties on the property list. The evaluator would do a (GET SYMBOL 'VALUE), just like it would do a (GET SYMBOL 'EXPR). It is obvious that these are both properties of a symbol, just like (GET SYMBOL 'SI:FLAVOR) is. Really, let's not go half-way. Let's take the argument for merging the VALUE and FUNCTION properties to its logical extreme, and eliminate the property-list altogether! Personally, I'd rather keep distinct meanings separate (noun-meaning (value), verb-meaning (function), adjective-meaning (flavor)), and try to have the most EXPRESSIVE language, not the SIMPLEST language. >Date: Mon, 5 Sep 1983 13:41 EDT >From: ZVONA@MIT-OZ >Subject: Function cells >In-reply-to: Msg of 3 Sep 1983 21:06-EDT from Robert W. Kerns <RWK at SCRC> Well. There are probably people who can argue this better, but none have stepped forward, so... What I don't understand is why everybody goes on about the FUNCTION cell in favor of the VALUE cell. Why isn't anybody proposing we do away with the VALUE cell. The history of the VALUE cell in MacLisp *IS THE SAME AS THAT OF THE FUNCTION CELL*. Really, let's not go half-way. Let's take the argument for merging the VALUE and FUNCTION properties to its logical extreme, and eliminate the property-list altogether! I think that is a good idea. (This step was seriously discussed in the design of T.) The whole idea of symbols is overloaded and bankrupt. The different uses and features of symbols ought to be separated out. First, there is the idea of INTERNED STRINGS, a useful user-interface feature. So we'll have such a datatype. Then there is the separate idea of NAMES: any object can name another; to an object, you can associate a value and retrieve it efficiently. (T lets you associate a value with any S-expression.) Quite another idea is that of PROPERTIES; Brand-X and (I think) MIT-scheme allow any object to have properties associated with it; there is nothing special about ``symbols''. I never use properties, myself; I think that they are almost always an artifact of unclear thought, and that you'd do better to use something else. The main uses are in user interface, when a user uses a symbol to name a structure, in which case you'd do better to use a hashtable that maps symbols to their associated structure; and in storing random crufties, in which case you should probably be using DEFSTRUCT. Unfortunately, naming is currently all mixed up with EVAL, which is pretty much bankrupt itself. The reason that currently symbols have values and not other things is that the main thing that gets values is EVAL, and other things mean something special to EVAL. So lists, for example, will not have their values used much, and from what I can see, T makes no use of the extended variable feature. Brian Smith's thesis straightens this particular mess out by replacing EVAL with two things: NORMALIZE, and DOWN-ARROW. DOWN-ARROW gets the ``value'' of something: the thing that is designated by its argument. NORMALIZE simplifies expressions. If you want to understand what QUOTE is really for, and how naming should work, you should read his thesis (it's an LCS TR). But his 2-LISP is probably too outre' to discuss on this mailing list. ... You can view (FUNCTION ...) as meaning "do what you do to the CAR of a combination to get the function to be performed". It doesn't buy you much to say that what you do with the FIRST of a form should be the same as what you do the the SECOND. It just isn't true after you get your hands on the function, especially in the case of macros. Your point here (which must be the crux of your argument) is not quite clear to me. Obviously the car of all forms can not be treated the same way as the other subforms; but in the case of special forms such as SETQ, various non-car subforms are treated in different ways anyway. The issue is meaningful only for forms that are simple combinations, i.e. function applications. [FUNCTION of a symbol that refers to a macro returns something completely random on the lisp machine, anyway. What does your last sentence mean?] The fact is that even for simple combinations, the CAR is treated specially, since it is the one that is applied to all the others. The claim is not that the uniformity of handling at this level is especially winning. The uniformity really arises from the fact that there is only one thing going on here, and that is NAMING. And the names of functions are no different from the names of anything else. I have seen many users of lisps without function cells SCREW THEMSELVES TO THE WALL by using something as a temporary variable that happens to also be a function name. LIST is the most common offender. (This is made worse by lisps which defaultly use dynamic scoping, but people also have screwed themselves doing (SETQ LIST (GET-ITEM-LIST 'FOO)) at top level). There are lots of ways to screw yourself when you are first learning Lisp. (Try tracing PRINT.) In a language that is lexically scoped and in which the system functions are locked and sacred (as, I believe, they are in MIT scheme) the danger is much reduced, and not worth making the language counter-intuitive over. because it is intuitively clearer if the defining and using forms have the same syntax. Moreover, this eliminates all the overhead of function specs. And then defun again has a clear macroexpansion: it is really just sugar for setf! Bullshit. DEFUN started out life as sugar for DEFPROP, not PUTPROP. The difference is that the compiler was then considered free to compile things defined with DEFPROP. In more modern times, the compiler is considered free to compile things "quoted" with FUNCTION rather than QUOTE. So... In an ideal world (which is not even particularly hard to achieve -- the MIT scheme implementation, at least, succeeds) there should be no difference between code to be compiled and code to be interpreted (except for declarations that will allow the compiler to optimize code without changing the semantics). It should never be necessary for the user to reason about differences between the behaviors of his program compiled and interpreted. Any sort of ``compilable contexts'' kludge such as #', special handling of DEFPROP, and (PROGN 'COMPILE ...) makes it much less clear what the compiler is doing, and harder to think about how to write code. You can't argue that because ((:property snabozzle quibbix) . args) doesn't work that the idea of a function spec is inelegant! At most you can say that a piece of it that should work doesn't. Certainly it would be an incremental improvement if this worked. In the current scheme, (DEFUN (:PROPERTY FOO :FUN-PROP) (X) (BAR X)) ==> (SETF #'(:PROPERTY FOO :FUN-PROP) #'(LAMBDA (X) (BAR X))) This doesn't work currently on the lisp machine. Presumably it does in the incomplete Common Lisp function spec proposal. (defun (symbol-value symbol) ...) ARGH! This does nobody any favors. It is every bit as bad as you imagine distinguishing between functions and values is. OK, fair enough, this sucked. Most of the people involved with Common Lisp have faced this issue and been thinking about it for 5 years or more. So have the Scheme people; so have I, for that matter. [Disclaimer: I do not work on any brand of Scheme, and am quite skeptical of all existing implementations. I use lisp machines, which are clearly a vastly superior programming system, even though the Lisp they are based on is a little crufty.] Most of the arguments against [function cells] are based on an unstated assumption that saying (FUNCALL X ...) is an unwanted complexity rather than a helpful clarification, or that the slight simplification of eliminating the function cell is worth sacraficing the clarity, or that the slight simplification of calling EVAL on the CAR of the form is worth anything at all. These assumptions aren't really unstated; they are firm convictions of many people. Some people that have programmed in languages both with and without funtion cells find those without to be much clearer; no sacrifice is involved. ----------------------------------------
notes@pur-ee.UUCP (11/17/83)
#R:decvax:-28100:iuvax:5800003:000:540 iuvax!mw Nov 16 08:49:00 1983 From: Mitchell Wand Indiana University In most versions of Scheme, the function position is evaluated normally, that is, the value of the expression in the function position is a function. The idea that the function position in Lisp is evaluated specially is associated, at least in my mind, with the fact that in most Lisps functions are not first-class citizens ("the upward Funarg problem"). I'm not sure about the historical reasons. See Sussman & Steele's MIT AI Memos on Scheme, or Abelson & Sussman's book (forthcoming).