[Openmcl-devel] Error: The function PRINT is defined as something other than a generic function
Gary Byers
gb at clozure.com
Sat Apr 2 02:25:31 PDT 2011
<http://www.gigamonkeys.com/book/object-reorientation-generic-functions.html>
is a chapter from Peter Seibel's book "Practical Common Lisp"; hardcopy of
that book is available from (among other places) Amazon:
<http://www.amazon.com/Practical-Common-Lisp-Peter-Seibel/dp/1590592395>
If you're just learning CL and CLOS, you'll probably find the answer
to your question easier to understand if you read that chapter or something
of similar scope. A short version of that answer (without the background
information that a tutorial would provide) is:
1) CL defines a subtype of FUNCTION - called GENERIC-FUNCTION.
2) A GENERIC-FUNCTION can have one or more METHODs associated with it.
3) A METHOD (in the simplest case, it can be more complicated than this)
associates a set of argument types with a function. The argument types
(classes, mostly) are often called the method's specializers.
All of the methods defined on a generic function have to accept (roughly)
similar arguments, and only required arguments can be specialized.
4) When called with an appropriate number of arguments, a GENERIC-FUNCTION
uses the types of the specializable arguments (mostly) to select a set
of one or more of the generic function's methods (a set of "applicable
methods") and calls them. (What happens when there's more or less than
one applicable method is interesting; read a tutorial.) The GENERIC-FUNCTION
doesn't implement any otherwise interesting behavior; its applicable methods
do. Methods can be added to (and removed from) a generic function at runtime
(and certainly during development); there are other ways of doing this,
but the most common way of defining a method and adding it to a generic function
is via the DEFMETHOD macro.
5) A non-generic function can't be incrementally augmented in this way. The
function named CL:+ is usually not generic, so there's no easy way to extend
it (to, for instance, allow it to be extended to perform addition on a user-defined
POLYNOMIAL type.) CL:+ is often used as a canonical example of a non-generic
function that could be implemented as a generic function. There are performance
and other tradeoffs involved, and (most ? all ?) CL implementations define
CL:+ as a non-generic function (but it's perfectly legal for an implementation
to define it generically.)
6) DEFMETHOD defines a named METHOD and adds it to the corresponding generic function.
What that means is that, when it's executed:
(defmethod name ...)
looks up the global function definition of NAME. If there's no global definition -
if (FBOUNDP NAME) is false - a new GENERIC-FUNCTION is installed as NAME's
global function definition and the method is added to that generic function.
If the global function definition of NAME is already a generic function, the
method is added to its set of methods (possibly replacing any previously-defined
method with the same set of specializers. And qualifiers, but we're ignoring
them for now.)
If neither of these conditions hold - NAME has a global function definition but
that definition isn't a GENERIC-FUNCTION - then the expansion of DEFMETHOD
must signal an error. (There'd be no way to add the method to a non-generic
function.)
This error is what you're seeing: CL:PRINT is defined as a non-generic function,
and there's no way for the code generated by DEFMETHOD to associate a METHOD with
that non-generic function. (The standard way of specializing the printer's
behavior is to define methods on #'CL:PRINT-OBJECT, which is required to be a
GENERIC-FUNCTION. CL:PRINT and other functions that ... print things ... call
PRINT-OBJECT to handle the details of printing specific types of objects.)
Some of the above is oversimplified to the point that it may not be entirely
accurate, but it's hopefully pretty close, and it's already a lot longer than
I'd intended it to be.
On Sat, 2 Apr 2011, Jason E. Aten wrote:
> I'm trying to define a print method for my class, and I'm getting "Error:
> The function PRINT is defined as something other than a generic function."
>
> Below shows the two commands that when issues, reproduce this on Linux
> x86_64.? What should I try instead?
>
> Apologies if this is obvious. I'm new to CLOS, and these classes are auto-
> generated by SWIG as wrappers for C++ classes.
>
> Jason
>
> jaten at afarm:~/dj/ldc2swig$ ccl -n
> Welcome to Clozure Common Lisp Version 1.7-dev-r14684M-trunk? (LinuxX8664)!
> ? (cl:defclass object()
> ? ((ff-pointer :reader ff-pointer)))
>
> #<STANDARD-CLASS OBJECT>
> ? (cl:defmethod print ((self object))
> ? (Object_dprint (ff-pointer self)))
>
> ;Compiler warnings:?????????????????????????????????????????????????????????????????????????
?? ???????????????????????????????????????????????????????????????????????????
?? ????????
> ;?? In (PRINT (OBJECT)) inside an anonymous lambda form: Undefined functionOBJECT_DPRINT?????????????????????????????????????????????????????????????
?? ??????????????????????????
>
> > Error: The function PRINT is defined as something other than a generic
> function.
>
>
> > While executing: ENSURE-GENERIC-FUNCTION, in process listener(1).
> > Type :GO to continue, :POP to abort, :R for a list of available restarts.
> > If continued: Try to remove any global non-generic function or macro
> definition.
> > Type :? for other options.
>
>
> 1 > :b
> ?(7FB61B6E6A10) : 0 (ENSURE-GENERIC-FUNCTION PRINT) 341
> ?(7FB61B6E6A40) : 1 (ENSURE-METHOD PRINT (#<STANDARD-CLASS OBJECT>)
> :FUNCTION #<Compiled Method-function (PRINT #) (Non-Global)? #x30200056D4BF>
> :QUALIFIERS NIL :LAMBDA-LIST (S\
> ELF)) 285
> ?(7FB61B6E6AA8) : 2 (FUNCALL #'#<Anonymous Function #x3020005682BF>) 157
> ?(7FB61B6E6AB8) : 3 (TOPLEVEL-EVAL (DEFMETHOD PRINT (#) (OBJECT_DPRINT #))
> NIL) 709
> ?(7FB61B6E6B60) : 4 (READ-LOOP :INPUT-STREAM #<SYNONYM-STREAM to
> *TERMINAL-IO* #x30200055A9ED> :OUTPUT-STREAM #<SYNONYM-STREAM to
> *TERMINAL-IO* #x30200055A63D> :BREAK-LEVEL 0 :\
> PROMPT-FUNCTION #<Compiled-function (:INTERNAL CCL::READ-LOOP) (Non-Global)?
> #x30000059B38F>) 2317
> ?(7FB61B6E6DC0) : 5 (TOPLEVEL-LOOP) 109
> ?(7FB61B6E6DF0) : 6 (FUNCALL #'#<(:INTERNAL (TOPLEVEL-FUNCTION
> (CCL::LISP-DEVELOPMENT-SYSTEM T)))>) 117
> ?(7FB61B6E6E10) : 7 (FUNCALL #'#<(:INTERNAL
> CCL::MAKE-MCL-LISTENER-PROCESS)>) 741
> ?(7FB61B6E6EB0) : 8 (RUN-PROCESS-INITIAL-FORM #<TTY-LISTENER listener(1)
> [Active] #x30200055776D> (#<COMPILED-LEXICAL-CLOSURE # #x302000556E8F>)) 717
> ?(7FB61B6E6F48) : 9 (FUNCALL #'#<(:INTERNAL (CCL::%PROCESS-PRESET-INTERNAL
> (PROCESS)))> #<TTY-LISTENER listener(1) [Active] #x30200055776D>
> (#<COMPILED-LEXICAL-CLOSURE # #x3020\
> 00556E8F>)) 389
> ?(7FB61B6E6F98) : 10 (FUNCALL #'#<(:INTERNAL
> CCL::THREAD-MAKE-STARTUP-FUNCTION)>) 301
> 1 >
>
>
>
More information about the Openmcl-devel
mailing list