From: Kenneth P. Turvey
Subject: How to determine if a function is compiled?
Date: 
Message-ID: <slrn66t89s.mf6.kturvey@pug1.sprocketshop.com>
I am looking at Steele's book (CLTL 2nd edition), trying to figure out
how a lisp program can determine if a function was previously
compiled.

On page 677 he states, "The consequences of calling compile on a
function that is already compiled are unspecified."

That is enough to let me know that I should avoid the behavior in any
case.

On page 685 he makes several references to functions of type
"compiled-function", but when I look at the types that may be checked
using typep (page 66) there isn't any mention of compiled-function.
In fact when I test a compiled function in gcl using the form:

(typep 'SA 'compiled-function)

the return value is nil.  So here I am... How do I check if a function
has been compiled.

I apologize if this is something obvious, I am new to lisp, and
struggling to gain some level of competence. 

Thanks,
-- 
Kenneth P. Turvey <·······@pug1.SprocketShop.com> 

If you pick up a starving dog and make him prosperous, he will not
bite you.  This is the principal difference between a man and a dog.
	-- Mark Twain

From: Kent M Pitman
Subject: Re: How to determine if a function is compiled?
Date: 
Message-ID: <sfwyb2mguxy.fsf@world.std.com>
·······@yorktown.cc.gatech.edu (Sunil Mishra) writes:

> ······@pug1.sprocketshop.com (Kenneth P. Turvey) writes:
>
> > I am ... trying to figure out how a lisp program can determine 
> > if a function was previously compiled. ...
> > (typep 'SA 'compiled-function)
> > the return value is nil.
>
> Try the function compiled-function-p

(compiled-function-p x) == (typep x 'compiled-function)

Both will return NIL for a symbol like SA.

Barry already answered this correctly, but I have a few footnotes to
add. I think part of the confusion stems from the fact that in CLTL1,
(functionp 'car) => T and in CLTL2, (functionp 'car) => NIL.
Now, in both CLTL1 and CLTL2, (compiled-function-p 'car) => NIL, which
is a bit odd, but if a person never called COMPILED-FUNCTION-P until
just now, they wouldn't see this confusing fact and they might have 
always thought that COMPILED-FUNCTION-P would (more consistently) have
returned true for 'CAR in CLTL1.

The problem was this: In CLTL1, FUNCTIONP returned true of functions,
symbols, and lists whose car was LAMBDA.  This caused an amazing
confusion because, after all, what were the "functions" that were a
subset of what FUNCTIONP was testing for?  We didn't like calling them
"functions" if they were only a subset of what FUNCTIONP returned true
for, so we called them "true functions" in conversation for a while.

There was an awful knock-down drag-out fight about how to fix this.
(OK, it wasn't that physical a fight, but I understand from the folks
in the movie business that my ratings will improve if I embellish a
little ... :-) I think the issue is FUNCTION-TYPE in the X3J13 issues,
if you want to refer to issue index in the Common Lisp HyperSpec(TM)
[CLHS].  What survives into the final writeup is only a pale shadow of
all the conflicting proposals that came before, but you can see from
the version history that there was a lot of fighting.  I think there
were also some competing proposals that failed that are not shown in
CLHS.

Ultimately, we incompatibly changed FUNCTIONP to return true only of
true functions, leaving symbols and conses whose car was LAMBDA just
that.   [It was just as well since this stuff about lists whose car
was LAMBDA had been awful, causing (functionp '(lambda . 3)) => T
and (functionp '(lambda (a a &bad-syntax))) => T.  And even the stuff
about symbols had ignored whether the symbol was fbound; which some
thought was good because of forward-references and some thought was
bad because they were about to call the function.  Suffice it to say
it was a mess, and it was fixed in dpANS, CLTL2, and ANSI CL, where 
those were NOT functions.  I think it was CLOS that finally forced the
fix because we needed a definitive class to dispatch on and while we
could have had the class FUNCTION span symbols (ick), we FORTUNATELY
could NOT have had the class FUNCTION span only those conses whose
cars were LAMBDA, so an incompatible change was forced.]

The compromise we worked out was that some of those (i.e., symbols)
could be used as functions (that is, they were funcallable) but they
were not themselves functions.  The reason for this was a simple and
practical observation that the mechanism for supporting coercing
symbols to functions at runtime was just #'symbol-function (i.e., a
slot access in many implementations) while the mechanism for
supporting coercing lists to functions was #'compile (i.e., a
compiler).  We decided that if you wanted to invoke the compiler and
risk that the compiler would be dumped out with your application, you
had to do more than (funcall f x) -- which in CLTL1 might potentially
invoke the compiler; you had to do (funcall (compile nil f) x).  In
this way, small systems which did not appear to call the compiler 
would in fact not call the compiler, and dumped applications wouldn't
have to contain a compiler "just in case".

Anyway, the result of this change is that now you consistently have
to do (functionp (symbol-function 'car)) and
(compiled-function-p (symbol-function 'car)).

Later, in dpANS and ANSI CL, I introduced the concept of designators.
We retroactively fit that concept to the solution already worked out,
but I bet it would have been a simpler discussion had the designator
concept already existed when we were trying to figure out this
"functionp" vs "funcallable" thing.

Designators are a syntactic device used for talking about the language;
they aren't a thing in the language.  So you don't have to know them
to know the language--but they make talking about the language a lot
easier.  If you aren't familiar with them, it's worth browsing CLHS
to learn about them.  (I've just made a note to myself to do something
in my 'Parenthetically Speaking' about this... gee, the list is getting
long--I'd better start writing some of these.)

CLHS can be found at:
 http://www.harlequin.com/education/books/HyperSpec/FrontMatter/

Download info for frequent users is at:
 http://www.harlequin.com/education/books/HyperSpec/
From: Sunil Mishra
Subject: Re: How to determine if a function is compiled?
Date: 
Message-ID: <efyg1okfmcx.fsf@peachtree.cc.gatech.edu>
In article <···············@world.std.com> ······@world.std.com (Kent M Pitman) writes:

   ·······@yorktown.cc.gatech.edu (Sunil Mishra) writes:

   > ······@pug1.sprocketshop.com (Kenneth P. Turvey) writes:
   >
   > > I am ... trying to figure out how a lisp program can determine 
   > > if a function was previously compiled. ...
   > > (typep 'SA 'compiled-function)
   > > the return value is nil.
   >
   > Try the function compiled-function-p

   (compiled-function-p x) == (typep x 'compiled-function)

[rest deleted... for conciseness]

Should have read the original post more carefully before suggesting
compiled-function-p...

Having used only CLtL2, I thought the only reasonable thing to do would be
to use (compiled-function-p #'car) rather than (compiled-function-p 'car),
and that is what my response was based on. I just didn't catch any of the
subtleties of the question. Thanks for the history lesson :-)

Sunil
From: Barry Margolin
Subject: Re: How to determine if a function is compiled?
Date: 
Message-ID: <64qon7$ef@tools.bbnplanet.com>
In article <······················@pug1.sprocketshop.com>,
Kenneth P. Turvey <·······@pug1.sprocketshop.com> wrote:
>In fact when I test a compiled function in gcl using the form:
>
>(typep 'SA 'compiled-function)
>
>the return value is nil.  So here I am... How do I check if a function
>has been compiled.

SA is a symbol, not a function, let alone a compiled function.  What you
probably meant to write was:

(typep (symbol-function 'sa) 'compiled-function)

You can also use

(compiled-function-p (symbol-function 'sa))

-- 
Barry Margolin, ······@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.
From: David B. Lamkins
Subject: Re: How to determine if a function is compiled?
Date: 
Message-ID: <B09A3C4E-22AB4E@206.163.127.168>
On Sat, Nov 15, 1997 11:31 PM, Kenneth P. Turvey
<··············@pug1.sprocketshop.com> wrote:
>I am looking at Steele's book (CLTL 2nd edition), trying to figure out
>how a lisp program can determine if a function was previously
>compiled.
>
>On page 677 he states, "The consequences of calling compile on a
>function that is already compiled are unspecified."
>
>That is enough to let me know that I should avoid the behavior in any
>case.

If I looked at this from a more optimistic viewpoint, I might interpret the
"unspecified" behavior to have something to do with a property of the
function not specifically related to its behavior.  For example, if I
called compile on a previously compiled function, I might expect the
compiler to create a new function which is not eq to a previously compiled
function. At high optimization levels, I might even expect that the
compiler would not necessarily replace already-compiled references to a
prior version of the compiled function.  However, I would not expect Lisp
to do something like totally ignore the new definition, or halt and catch
fire...

Dave
From: Kent M Pitman
Subject: Re: How to determine if a function is compiled?
Date: 
Message-ID: <sfw7ma268zm.fsf@world.std.com>
"David B. Lamkins" <········@teleport.com> writes:

> On Sat, Nov 15, 1997 11:31 PM, Kenneth P. Turvey wrote:
>
> >On page 677 he states, "The consequences of calling compile on a
> >function that is already compiled are unspecified."
>
> If I looked at this from a more optimistic viewpoint, I might interpret the
> "unspecified" behavior to have something to do with a property of the
> function not specifically related to its behavior.  For example, if I
> called compile on a previously compiled function, I might expect the
> compiler to create a new function which is not eq to a previously compiled
> function. At high optimization levels, I might even expect that the
> compiler would not necessarily replace already-compiled references to a
> prior version of the compiled function.  However, I would not expect Lisp
> to do something like totally ignore the new definition, or halt and catch
> fire...

Well, you can always send your wishes to a vendor and hope, but I
wouldn't write code depending on an optimistic assumption.  I strongly
recommend coding "defensively".

This innocent looking phrase is actually covering an enormous amount of 
potential implementation variance:

 (1) The program might have called compile on the wrong function, and some
     implementations might signal an error to let you know that you goofed.

 (2) Some might incorrectly assume that in this case:

      (defmacro frob (x) `(car ,x))
      (defun foo (x) (frob x))
      (compile 'foo)
      (defmacro frob (x) `(cdr ,x))
      (compile 'foo)

     The recompilation would pick up the new macro definition.  Unfortunately,
     the implementation is not required to keep the source code, so may have
     no way to recompile.  Note that maintaining source is very iffy and potentially
     expensive, so we left it to vendors.

 (3) Some might want it to just assure that it's already compiled, and be
     an identity, while others might want it to "compile more".
     Mostly I think the latter expectation is unreasonable--recompiling from
     the original sources with different declarations seems to me better, but
     is impractical because (as I mentioned above) source may no longer be around.

 (4) We couldn't REQUIRE implementations to signal an error because some implementations
     are compiled-only, and so they'd blow up onthe first call to compile in the 
     example above--in compiled-only implementations, presumably compiling an 
     already-compiled function is a no-op.