When I call (draw win) I get an error the "generic function can't find applicable method. I have just gotten into CLOS and I am using sdl2kit to simply render a window.

(defclass game-window (kit.sdl2:window)
  ((rotation :initform 0.0)))

(defmethod render ((win game-window))
 (with-slots (rotation) win
 (gl:rotate rotation 0 0 1)
 (gl:clear-color 0.0 0.0 1.0 1.0)
 (gl:clear :color-buffer)
 (gl:begin :triangles)
 (gl:color 1.0 0.0 0.0)
 (gl:vertex 0.0 1.0)
 (gl:vertex -1.0 -1.0)
 (gl:vertex 1.0 -1.0)
(defgeneric draw(win)
 (:documentation "draw window"))
(defun main ()
 (let (( win (make-instance 'game-window)))
  (draw win)))
  • 2
    The code only has the definition for the generic function, but that won't do anything by itself. You also need to define a method specializing it for GAME-WINDOW. See for example the Practical Common Lisp Chapter 16 – jkiiski Feb 17 '17 at 16:46
  • I have already read this page but I am still having trouble understanding the book's examples. I thought defgeneric will call a method according to the specializer. I thought my render method already has "game-window" specializing "win" with render ((win game-window)). – ZhangBing Feb 17 '17 at 17:18
  • 4
    I thought my render method already has "game-window" specializing "win" with render ((win game-window)). Aren't you confusing draw with render? You did define a method for render but none for draw. – coredump Feb 17 '17 at 17:31
  • DEFGENERIC doesn't call anything. It defines a generic function, in this case one named DRAW, which can be specialized for different kinds of arguments by defining methods (just like the method you have for RENDER). – jkiiski Feb 17 '17 at 17:33
  • 2
    Simple: one generic function can be specialized by different methods. Each method is named like the generic function, but it differentiates itself from other methods of the generic function thanks to its specializers (types of its arguments) and qualifiers (around, before, after, ...). Now, when you issue a defmethod without a previous defgeneric, the generic function is defined automatically. – coredump Feb 17 '17 at 20:20

So there are two issues. One is an English language issue (you have to be super careful because every English word is overloaded with multiple programming meanings. Eg when you write “call” it isn’t clear whether you mean “name” or “invoke/apply”.) but that doesn’t really matter

The other issue is that you don’t know what a generic function is. Here is a quick explainer.

A generic function has (roughly) three parts:

  1. A lambda list
  2. A method combination
  3. A set of methods

A method has three parts

  1. A specialised lambda list
  2. Some code
  3. Something related to the method combination (typically nil)

When you call a generic function this happens:

  1. It looks at the types of the arguments
  2. Various rules are applied to order the methods by specificity
  3. The method combination says how to combine these into a function
  4. The code for the combined function is generated and compiled
  5. The generated function is called with the arguments.

Steps 2-4 are typically cached.

Step 3 comes in roughly two forms:

  1. Standard method combination:
    1. All around methods are called
    2. Then all before methods
    3. Most specific method is called (with an appropriate chain of methods set up for call-next-method)
    4. Then all after methods
    5. Result is returned through all the around methods
  2. Other method combinations typically apply all the methods’ results to some operator like and or progn or append.

To add a method to the set of methods of a generic function one typically uses defmethod with the same name as the generic function

Your Answer

