Lisp - Generic Functions



Generic Function

Generic functions in LISP provides a powerful mechanism to define and dispatch functions based on types of arguments passed. A generic function is defined using defgeneric macro. A generic function is similar to interface in Java. A generic function provides the interface of a function without specifying the implementation.

Example - Defining Generic Function

Following code shows declaration of a generic function.

; define a generic function 
(defgeneric greet (Person))

Method

A method implements signature specified by the generic function. A method is defined using defmethod macro. A method is associated with specializers, based on specific argument types.

Example - Defining Methods implementing Generic function

Following code shows declaration of a generic function.

; define a generic function 
(defgeneric greet (Person))

; define a method accepting a string
(defmethod greet ((Person string))
   (format t "Hello, ~a!~%" Person))

; define a method accepting the person object
(defmethod greet ((Person Person))
   (format t "Greetings, ~a!~%" (person-name person)))

Important Concepts

  • Dispatch − When generic function is called, CLOS determines the associated function to be called based on the type of argument passed. This process is termed as dispatch. CLOS supports multimethods as well like dispatch based on types of multiple arguments.

  • Specializers − A specializer is used to specify the type of argument that a method applies to when a method is defined using defmethod

  • Method Combination− CLOS provides capability to combine results of multiple methods when a generic function is called.

Example - Generic Function

Following is the complete example of a generic function.

main.lisp

; define a class
(defclass person ()
   ((name :accessor person-name)))

; define a generic function
(defgeneric greet (person))

; define a method implementing generic function accepting string
(defmethod greet ((person string))
   (format t "Hello, ~a!~%" Person))

; define a method implementing generic function accepting person object
(defmethod greet ((person person))
   (format t "Greetings, ~a!~%" (person-name person)))

; define a class
(defclass person ()
   ((name :accessor person-name)))

; create object of Person
; create an instance of class box and assign to an item
(setf robert (make-instance 'person))

; set name of the person as Robert
(setf (person-name robert) "Robert")

; dispatch generic function based on string
(greet "Adam")

; dispatch generic function based on object
(greet robert)

Output

When you execute the code, it returns the following result −

Hello, Adam!
Greetings, Robert!
Advertisements