Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

LISP evaluator question

11 views
Skip to first unread message

David Betz

unread,
Nov 15, 1983, 5:48:24 PM11/15/83
to
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

Stanley Shebs

unread,
Nov 16, 1983, 4:30:38 AM11/16/83
to
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

Harold Carr

unread,
Nov 16, 1983, 3:34:34 PM11/16/83
to
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 (CA...@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: Deuts...@PARC-MAXC.ARPA
>Subject: Re: function cells
>In-reply-to: "PAD...@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: Bobr...@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: Bobr...@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: Deuts...@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: Bobr...@PARC-MAXC.ARPA
>Subject: Re: Function cells
>In-reply-to: "BEN...@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.

----------------------------------------

0 new messages