From: jeff@aiai.edinburgh.ac.uk (Jeff Dalton)
Subject: Re: How to neatly destroy instances?
Organization: The Ohio State University Department of Computer and Information Science
Date: Thu, 15 Oct 1992 18:47:42 GMT

> > From: jeff@aiai.edinburgh.ac.uk (Jeff Dalton)
> > 
> > > I don't think finalizations belong in the language standard -- they
> > > are a non-standard agreement between application writer and the
> > > implementation's storage management system.   [...]
> > >
> > > Anyway, my advice is never to use finalizations for _computational_
> > > effect.
> > 
> > That looks like good advice to me, but I disagree that finalization
> > doesn't belong in the standard.  Very similar reasoning (IMHO) was
> > used against FIXNUM declarations.

> The present standard doesn't even describe an interface to the garbage
> collector itself -- such as the GC function in most implementations
> that express the notion "I'd like gc to happen now rather than waiting
> until it becomes necessary." 

Ok, I think I may have misunderstood you, at least in part.
If the question is whether finalization should be in the current
standard, or in the kind of standard we have now (sufficiently
narrowly defined), then the answer may well be "no".

Where I start to disagree is where there are arguments that seem
to say or imply that finalization is just the wrong kind of thing
to put in any standard.  That it's inherently a non-standard
agreement between application writer and the implementation's 
storage management system, for instance.

I think we ought to be pragmatists about standards and not let
essentialist (sorry, but I can't think of a better word right now)
notions of what standards are prevent us from specifying something we
think ought to be specified.  If someone said standards specify this
kind of thing and not some other kind of thing, because that's just
what standards are, then I'd say this: if we can tell each other
how something works in Common Lisp, then we can put it in the
standard -- if we want to.

(I'm not trying to say you take this essentialist stance; it's
just the extreme end, shall we say, of a way of thinking I 
disagree with.)

> Indeed, I can't recollect that the spec
> even mentions garbage collection anywhere.  Why would it?  Garbage
> collection is not perceivable in the semantics of Common Lisp. 

But we get to say what the semantics are.  If we want to say
garbage collection happens, we can.

> I think you're can't have it both ways: finalizations cannot be both a
> good thing to avoid and a good thing to have in the standard.

I'm not saying they're a good thing to have or to have in the standard
(I'm not sure whether they're good), merely that we can have them in
the standard if we want to. 

> The standard pretty much restricts itself to the behavior of programs
> at the algorithmic level, not the performance and implementational
> level.

True, and there may be compelling reasons to keep it that way.

> Your mention of the FIXNUM type declaration is illuminative.  As a
> compiler writer, I have long felt that the FIXNUM declaration is
> usually not appropriate in user-written code.  When a random
> programmer writes the FIXNUM declaration, he usually means: "This
> value will be an integer sufficiently small to be safely represented
> by the FIXNUM data type."  But why is the programmer jumbling up his
> "high-level" knowledge about the algorithic behavior of his program
> with assumptions about the "low-level" representation that the program
> should use?  Deciding on the mosty efficient data representation (in a
> high level language) is the job of the compiler, not the programmer.

This is a reasonable point of view, given sufficiently good,
and widely available, compilers -- and machines that can handle
the fixnum case of generic arithmetic fast enough: because
it's not always possible for a compiler to deduce everything
that the programmer can tell it.

> Furthermore, the FIXNUM declaration is just sloppily imprecise.  If
> the programmer is really confident that a value will be in fixnum
> range, it must be that he really knows its range of possible values.

Not always.  For example, I can write something like this:

  (if (typep current-max 'fixnum)
      (fixnum-version ...)
    (general-version ...))

That is, I (or my program) may not know the range of values until
run-time.  Sure, it's low-level.  But programs sometimes have to
be low-level.  They can have other, higher, levels in which everything
is more abstract.

Moreover, X3J13 made the decision (rightly in my opinion) to make
fixnums always work as array indices.

> If so, then it is unproductive to withhold any additional constraint
> information from the compiler.  If the compiler has been told only that
> AGE is a FIXNUM, then it can't justifiably infer that (1+ AGE) or (*
> AGE 12) are also FIXNUM.  But if the programmer tells the compiler
> that AGE is, say, (INTEGER 0 150), then the compiler can infer that
> each of those computed results are also FIXNUM.  

This is true, but there are a number of cases where I don't
know the limit or where the limit is even more artificial than
FIXNUM.  For instance, why should I write code for vectors
with as many as, say, 1000 elements when I can write instead
for "vectors as big as this Lisp can handle"?  Why should I
have to pick a number?

> The moral is that
> algorithms should be defined in "algorithmic space" terms such as
> (INTEGER low high) not "implementational space" terms such as FIXNUM.

In practice, if fixnum declarations were eliminated programmers 
would pick artificial limits in order to get more efficient code.
(INTEGER 1 x) can be just as "implementation space" as FIXNUM.

> The intention of my earlier message is that whatever place
> finalizations might have in the communication between an application
> and a lisp implementation, they are in "implementational space" not in
> "algorithmic space."  I realize these domains are fuzzy and have
> overlap, but (I believe) the separation is nonetheless an important
> principle in software design.

It may well be an important principle in software design, but it
doesn't follow that a standard can address only one of these spaces.
Indeed, standards will always constrain at least some aspects of
implementations.  

If finalization is sufficiently more useful than harmful, and
if we want programmers to be able to use it, then it is better
(for these programmers) if they can request finalization in
the same way in all implementations where it makes sense.
And that is an argument, though not necessarily a conclusive
argument, for putting it in the standard.

I believe very strongly that Common Lisp is, and should be, a
practical language that addresses the problems we actually face
rather than an ideal language in which practical considerations
always lose to principles.  I suspect that most people agree,
to an extent, but disagree on where to draw the line, which
is fair enough.

-- jd
Newsgroups: comp.lang.clos