Methods in Lisp

Our example demonstrates how to define methods on struct types in Lisp using the Common Lisp Object System (CLOS).

(defpackage :methods-example
  (:use :cl))

(in-package :methods-example)

;; Define a struct equivalent
(defclass rect ()
  ((width :initarg :width :accessor width)
   (height :initarg :height :accessor height)))

;; This 'area' method is defined for the 'rect' class
(defmethod area ((r rect))
  (* (width r) (height r)))

;; Methods can be defined for either the class itself or its instances
;; Here's an example of a method defined on the class
(defmethod perim ((r rect))
  (+ (* 2 (width r)) (* 2 (height r))))

(defun main ()
  (let ((r (make-instance 'rect :width 10 :height 5)))
    ;; Here we call the 2 methods defined for our class
    (format t "area: ~A~%" (area r))
    (format t "perim: ~A~%" (perim r))
    
    ;; In Lisp, there's no distinction between value and pointer receivers
    ;; All object parameters are effectively passed by reference
    (format t "area: ~A~%" (area r))
    (format t "perim: ~A~%"(perim r))))

;; Run the main function
(main)

To run the program:

$ sbcl --script methods.lisp
area: 50
perim: 30
area: 50
perim: 30

In this Lisp example, we use CLOS to define a rect class and its methods. The area and perim methods are defined using the defmethod macro, which allows for method dispatch based on the class of its arguments.

Unlike Go, Lisp doesn’t have a concept of pointer vs. value receivers. All object parameters in Lisp are effectively passed by reference, so there’s no need to explicitly use pointers.

The main function demonstrates creating an instance of the rect class and calling its methods. In Lisp, we don’t need to distinguish between calling methods on values or pointers as we would in Go.

Next, we’ll look at Lisp’s mechanism for defining abstract interfaces and polymorphism: generic functions and method combinations.