[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Function cells



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.