0

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:load-identity)
 (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)
 (gl:end)))
(defgeneric draw(win)
 (:documentation "draw window"))
(defun main ()
 (let (( win (make-instance 'game-window)))
  (draw win)))
Rainer Joswig
  • 136,269
  • 10
  • 221
  • 346
ZhangBing
  • 45
  • 1
  • 11
  • 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](http://www.gigamonkeys.com/book/object-reorientation-generic-functions.html) – 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
  • Oh so they have to have the same name? So I have to make a defgeneric render fucntion? I thought generic functions and methods couldn't have the same name that is why I am confused. – ZhangBing Feb 17 '17 at 17:34
  • DEFMETHOD creates a generic function if there isn't one. You can always use DEFGENERIC to specify more options. But in your example it should be obvious that DRAW does nothing, since it has no code... – Rainer Joswig Feb 17 '17 at 17:41
  • Yes and I thought the only purpose of generic functions were to use it to call a method but @jkiiski said that generic functions do not call anything. I will look at the specify option. Sorry I am new to lisp and the whole concept of generic fucntions got me really confused cause I am not sure what generic functions do "under the hood" or not. If DRAW was a DEFUN I would understand that it would not do anything cause their is no code. – ZhangBing Feb 17 '17 at 17:47
  • 3
    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

1 Answers1

1

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

Dan Robertson
  • 4,315
  • 12
  • 17