Next: , Up: multimethods   [Index]


19.1 Examples of method dispatching

Here we look at some examples of what we have to expect from multimethods dispatching. We will always assume that the code in the examples is wrapped into a program form as follows:

#!vicare
(program (demo)
  (options typed-language)
  (import (vicare)
    (vicare language-extensions multimethods))

  ... ;here goes the code

  #| end of program |# )

Let’s examine an example using the generic functions definer define-generic:

(define-record-type <one>                  (nongenerative one))
(define-record-type <two>   (parent <one>) (nongenerative two))
(define-record-type <three> (parent <two>) (nongenerative three))

the type hierarchy is:

<top> -> <struct> -> <record> -> <one> -> <two> -> <three>

the list of UIDs for <three> is:

(type-unique-identifiers <three>)
⇒ (three two one
    vicare:scheme-type:<record>
    vicare:scheme-type:<struct>
    vicare:scheme-type:<top>)

so for the generic function:

(define-generic doit (o))
(define-method (doit {o <one>}) 'one)
(define-method (doit {o <two>}) 'two)

applied to a value of type <three>: the method with <two> in the signature is more specific than the method with <one> in the signature:

(doit (new <three>)) ⇒ two

also the method with <one> in the signature is the “next method” of the method with <two> in the signature, we can call it using call-next-method. The following example shows a call to the next method:

(define-generic fluff (o))

(define-method (fluff {o <one>})
  'one)

(define-method (fluff {o <two>})
  (cons 'two (call-next-method)))

(define o (new <three>))

(fluff o)
⇒ (two . one)

The syntax define-generic defines a macro which can be used as a function; the syntax define-method adds a new method to the generic function; define-generic establishes the number of arguments for the generic function: all the methods must have the same number of arguments.

It is possible to define a function accepting different numbers of arguments as follows:

(case-define fluff
  ((a)
   (fluff-1 a))
  ((a b)
   (fluff-2 a b))
  ((a b . rest)
   (fluff-3 a b rest)))

(define-generic fluff-1 (o))
(define-generic fluff-2 (o p))
(define-generic fluff-3 (o p rest))

(define-method (fluff-1 {o <one>})
  ---)

(define-method (fluff-2 {o <one>} {p <two>})
  ---)

(define-method (fluff-3 {o <one>} {p <two>} rest)
  ---)

this way we turn a set of macros into a single “generic function” which is truly a function. If we avoid wrapping the macros into a function we may gain a bit of speed in function calls.


Next: , Up: multimethods   [Index]