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

edit definition



    Date: Fri, 15 Jun 90 11:46 PDT
    From: Charest@AI-SUN.jpl.nasa.gov (Len Charest)

    When I define a LISP structure, Zmacs "knows" that the definitions of
    the accessor functions, predicate function, etc. are inside the
    structure definition. Now I want to define my own macro with much of
    the same functionality:

	    (defmacro deffoo (name)
	      (let ((predicate (intern (format nil "~a-P" name))))
	      `(progn (blah-blah-blah)
		      (defun ,predicate (x)
			(typep x ',name))
		      ',name)))

    Example: (deffoo boo-boo)
    => (PROGN (BLAH-BLAH-BLAH)
	      (DEFUN BOO-BOO-P (X)
		(TYPEP X 'BOO-BOO))
	      'BOO-BOO)

    Defun automatically records the source file name for boo-boo-p, but
    Zmacs cannot find the embedded definition. It gives me an annoying
    message like "Can't find definition for BOO-BOO-P; trying textual
    search." How can I get Zmacs to correctly find this embedded
    definition a la defstruct?

DEFSTRUCT uses a nifty special operator called SYS:MULTIPLE-DEFINITION.
Instead of PROGN, say the following:

  (defmacro deffoo (name)
    (let ((predicate (intern (format nil "~a-P" name))))
      `(sys:multiple-definition ,name deffoo
	  (blah-blah-blah)
	  (defun ,predicate (x)
	    (typep x ',name))
	  ',name)))

This works for things where your definition looks like 

   (def-thing <name-of-thing> ...)

If you want to have the name parenthesized, or the name is derived somehow
from the form (other than using CADR), you might have to tell Zmacs how to
parse the form.  Look at the definition of ZWEI:DEFSELECT-FUNCTION-SPEC-FINDER
to see how this is done for DEFSTRUCT (I figured this out by asking Genera for
the property list of DEFSTRUCT, by the way; some other symbols whose property
lists contain interesting things include DEFFLAVOR, DEFMETHOD, DEFMACRO, etc.)

Warning: SYS:MULTIPLE-DEFINITION does not work for compiled code which
defines both a flavor and a method on that flavor -- it will blow up at LOAD
time.  Since flavors don't get function-parents the way functions do, that's
not too important.  If you want to define a flavor inside a macro expansion,
you have to use SI:DEFFLAVOR-WITH-PARENT, so you can put that inside a PROGN
around the SYS:MULTIPLE-DEFINITION for the rest (even if it's only one form,
use SYS:MULTIPLE-DEFINITION; it gives you function-parent properties):

   (defmacro define-flavor-and-predicate (name instance-variables component-flavors
					  &rest flavor-options)
     (let ((predicate-name (sys:fintern "~A-P" name)))
       `(progn (si:defflavor-with-parent
		 (,name define-flavor-and-predicate)
		 ,name
		 ,instance-variables (,@component-flavors my-base-flavor)
		 ,@flavor-options)
	       (sys:multiple-definition ,name define-flavor-and-predicate
		  (eval-when (compile load eval)
		    (pushnew ,name *my-flavor-names*))
		  (defmethod (,predicate-name ,name) () t)
		  (defmethod (,predicate-name my-base-flavor) () nil)))))

Will turn something which looks sort of like a DEFFLAVOR into a true
DEFFLAVOR, two methods, and also will register the flavor name at COMPILE,
LOAD and EVAL times.

[I recommend you read the answers from RWK and SGR about this as well; they
have some good suggestions.]