From: Barry Margolin
Subject: Re: Questions about CL
Date: 
Message-ID: <1lq40sINNj0c@early-bird.think.com>
In article <······················@uk03.bull.co.uk> ······@hemel.bull.co.uk (Bill Birch) writes:
>1.	Why did X3JI�3 vote to disallow expressions like:
>
>	(mapcar '(lambda (x y) (sqrt (* x y))) p q)
>
>	"This makes it impermissible to represent a lexical closure
>	as a list whose CAR is some special marker". 
>	(CLtL2 p 37)

From the FUNCTION-TYPE cleanup issue:

 Lambda-expressions do not obey the normal, apparent scoping rules because
 free variables cannot refer to lexical bindings.  This is because
 coercing a list to a function would mean (EVAL `(FUNCTION ,list)).
 ...
 Making the coercion of lambda-expressions to functions explicit with
 the use of EVAL will encourage less confusing code and also highlight
 that use of EVAL.

We still allow symbols to be used in many cases where functions are
expected as a compromise.  There's lots of existing code that does stuff
like (funcall *foo-hook*), where users do something like (setq *foo-hook*
'my-foo-function).  This allows them to redefine MY-FOO-FUNCTION without
having to afterward reassign all the places where it might have been
stored.  But this is less of an issue with anonymous functions, since they
can't be redefined.

>2.	Why is it "an error to use the FUNCTION special form on a symbol
>	that denotes a macro or special form"? (CLtL2 p 116)
>	Does this mean that you cannot pass macros to functions in CL?
>	Surely if the code is not compiled, that could be quite useful.

Why would it be useful?  Macros perform syntactic transformations; what
does it mean to call it at run time when you expect to be calling a normal
function?  Special forms are processed specially by the
compiler/interpreter; it makes even less sense to call them.

You *can* call the macro's expander function; see the MACRO-FUNCTION
function.

>3.	What are the CL equivalents of the old SUBR and FSUBR data types?

The CL equivalent to SUBR is COMPILED-FUNCTION.

There's nothing like FSUBR; SPECIAL-FORM-P will tell whether a symbol is a
special operator, but there's no requirement that special operators be
implemented using a distinct function type.  There's no standard way for
users to define new special operators, nor can they portably redefine the
symbols that name special operators, so an implementation may simply
contain code like this in the compiler and interpreter:

(case (car form)
  (let (process-let (cdr form)))
  (cond (process-cond (cdr form)))
  ...
  (otherwise (process-normal-form form)))
-- 
Barry Margolin
System Manager, Thinking Machines Corp.

······@think.com          {uunet,harvard}!think!barmar

From: Bill Birch
Subject: Re: Questions about CL
Date: 
Message-ID: <1993Feb16.175508.12582@uk03.bull.co.uk>
······@think.com (Barry Margolin) writes:

>>2.	Why is it "an error to use the FUNCTION special form on a symbol
>>	that denotes a macro or special form"? (CLtL2 p 116)
>>	Does this mean that you cannot pass macros to functions in CL?
>>	Surely if the code is not compiled, that could be quite useful.

>Why would it be useful?  Macros perform syntactic transformations; what
>does it mean to call it at run time when you expect to be calling a normal
>function?  Special forms are processed specially by the
>compiler/interpreter; it makes even less sense to call them.

Well suppose you want to trace a macro, or count the number
of invocations. The example code below changes a function
or macro so that a count of the number of times it is called 
is maintained in it's plist. The line with APPLY accepts
macros. This works because the interpreter views a macro
as a function which does not evaluate its arguments. 

Seen from this point of view, it makes sense to pass even things like
cond, if etc so they can be traced or profiled. (assuming that cond
is not a special form!).

Or put another way, what is the CL equivalent of Standard Lisp's DF?

Bill

PS Thanks for your explanations of my questions 1. and 3. :-)

;;-------------------------------------------------------------------
;;
;; Wrap function calls with a counter increment.
;;
;; NOT Common Lisp!
;;
(defun profile-aux (fn)
   (put fn 'olddef (symbol-value fn))   ; save old definition
   (put fn 'count 0)   					; initialise counter
   (set fn 								; over-write old value
      `(,(cond
	  		((equal (type-of (symbol-value fn)) 'subr) ; subr eval args
				'lambda)
	  		((equal (type-of (symbol-value fn)) 'fsubr) ; fsubr no eval
				'lambdaq)				; Compiled macros or DFs 
	  		((consp (symbol-value fn))
				(car (symbol-value fn)))) ; not compiled so copy
			(&rest *x)
	  	 (put ',fn 'count (+ 1 (get ',fn 'count))) ; counter++
		 (apply (get ',fn 'olddef) *x)	; Call the function/macro
          ))
   fn )
--
 Bill Birch             	|	·······@uk03.bull.co.uk
 Bull Info. Sys. Ltd.   	|       Bull Tel: 773 4770
 Maxted Road,         		|	Bull Mail: HM14 UK03 
 Hemel Hempstead,        	|	Tel: +44 442 884770
 HERTS, HP2 7DZ, U.K.         	|	Fax: +44 442 884570
                Aviate, Navigate, Communicate...
From: Dorai Sitaram
Subject: Re: Questions about CL
Date: 
Message-ID: <C2KBzx.Jzs@rice.edu>
Is there any standard, de facto or otherwise, about the
possible symbols that could be included in *features*?  CLtL
mentions only one standard feature name, viz.,
'ieee-floating-point.  How about others?  E.g., can I be
assured that 'compiler will be in *features* if and only if
the implementation has compile-file?

--d
-- 

·····@cs.rice.edu      !    It may be that the gulfs will wash us down;
·····@owlnet.rice.edu  !      it may be we shall touch the Happy Isles.
From: Barry Margolin
Subject: Re: Questions about CL
Date: 
Message-ID: <1lsoudINN5o7@early-bird.think.com>
In article <··········@rice.edu> ·····@cs.rice.edu (Dorai Sitaram) writes:
>Is there any standard, de facto or otherwise, about the
>possible symbols that could be included in *features*?  

The dpANS adds a few more standard features allow you to determine which
version of the language an implementation conforms to: :CLTL1, :CLTL2,
:X3J13, :DRAFT-ANSI-CL, ANSI-CL.  And it adds :COMMON-LISP, which should
appear in any Common Lisp implementation.

>							 CLtL
>mentions only one standard feature name, viz.,
>'ieee-floating-point.  

Actually, it's :IEEE-FLOATING-POINT.  The standard has no symbols with
quotes in their names, as they require escaping when typing them.

>			How about others?  E.g., can I be
>assured that 'compiler will be in *features* if and only if
>the implementation has compile-file?

Currently, all CL implementations must have COMPILE-FILE.  There were some
public review comments suggesting standard subsets, and *FEATURES* would
probably be used to indicate which subsets are present.  But this has not
been adopted yet (it's on our agenda for our meeting next month).

-- 
Barry Margolin
System Manager, Thinking Machines Corp.

······@think.com          {uunet,harvard}!think!barmar
From: Barry Margolin
Subject: Re: Questions about CL
Date: 
Message-ID: <1ls2n6INNjop@early-bird.think.com>
In article <······················@uk03.bull.co.uk> ······@hemel.bull.co.uk (Bill Birch) writes:
>······@think.com (Barry Margolin) writes:
>
>>>2.	Why is it "an error to use the FUNCTION special form on a symbol
>>>	that denotes a macro or special form"? (CLtL2 p 116)
>>>	Does this mean that you cannot pass macros to functions in CL?
>>>	Surely if the code is not compiled, that could be quite useful.
>
>>Why would it be useful?  Macros perform syntactic transformations; what
>>does it mean to call it at run time when you expect to be calling a normal
>>function?  Special forms are processed specially by the
>>compiler/interpreter; it makes even less sense to call them.
>
>Well suppose you want to trace a macro, or count the number
>of invocations. The example code below changes a function
>or macro so that a count of the number of times it is called 
>is maintained in it's plist. The line with APPLY accepts
>macros. This works because the interpreter views a macro
>as a function which does not evaluate its arguments. 

Your code doesn't even work for ordinary functions, since it uses
SYMBOL-VALUE and SET to get and change the function binding of the symbol,
rather than SYMBOL-FUNCTION and SETF of SYMBOL-FUNCTION.  But perhaps
that's correct for the dialect of Lisp it's written in (it's clearly not CL
since it uses PUT).

However, once that's fixed, it can be made to work for macros as well by
using MACRO-FUNCTION.  Here's some (untested) code:

(defun profile-aux (fn)
  (when (special-operator-p fn) ; this is called SPECIAL-FORM-P in CLtL
    (error "Can't profile special operator ~S." fn))
  (when (get fn 'old-def)
    (unprofile-aux fn)) ; don't nest profiles
  (let* ((macro-def (macro-function fn))
         (old-def (or macro-def (symbol-function fn))))
    (unless old-def
      (error "~S is not defined." fn))
    (setf (get fn 'count) 0
	  (get fn 'old-def) old-def)
    (flet ((new-def (&rest args)
	     (incf (get fn 'count))
	     (apply old-def args)))
      (if macro-def
          (setf (macro-function fn) #'new-def)
	  (setf (symbol-function fn) #'new-def)))))

(defun unprofile-aux (fn)
  (let ((old-def (get fn 'old-def)))
    (if old-def
        (progn 
          (if (macro-function fn)
              (setf (macro-function fn) old-def)
	      (setf (symbol-function fn) old-def))
          (remprop fn 'old-def))
        (cerror "Continue" "~S is not being profiled." fn))))

>Seen from this point of view, it makes sense to pass even things like
>cond, if etc so they can be traced or profiled. (assuming that cond
>is not a special form!).

As long as you are aware that macros may not be "called" when you expect
them to be.  Some interpreters expand all the macros in a function at the
time it is defined, instead of expanding them each time the function is
called.  And some "interpreters" actually compile everything; they
implement EVAL as something like this:

(defun eval (form)
  (funcall (compile nil `(lambda () (progn ,form)))))

(I say "something like", because it has to arrange for EVAL-WHEN to treat
it as a :EXECUTE situation rather than :COMPILE-TOPLEVEL.)

In fact, You could probably use your profiling facility to determine what
kind of evaluator you're in!
-- 
Barry Margolin
System Manager, Thinking Machines Corp.

······@think.com          {uunet,harvard}!think!barmar