Lisp - :before Method Combination



:before is one of the standard method combination in CLOS.:before is a powerful way to execute code before the primary method. In this chapter, we're discussing how to create and apply functions using :before with a running example. A :before keyword is very useful in achieving the following−

  • To Set up preconditions before executing the generic function.

  • Log or trace method calls.

  • To perform preliminary calculations.

  • To validate inputs.

Defining :before function

A :before function is defined using following syntax

; define a generic function
(defgeneric process-data (data))

; define generic before function to be called before generic function for data
(defmethod process-data :before ((data t))
  (format t "process-data is called: ~a~%" data))
  
; define integer specific before function to be called before generic function for data
;(defmethod process-data :before ((data integer))
  (format t "Integer specific process-data is called: ~a~%" data))
  • defmethod process-data :before ((data t)) − a generic before function is defined on a generic function process-data. It will be called after all applicable generic functions.

  • defmethod process-data :before ((data integer)) − before function is defined on a generic function process-data. It will be called before integer based generic functions.

Example - :before Function

Following is the complete example of a :before function.

main.lisp

; define a generic function
(defgeneric process-data (data))

; define a generic before method
(defmethod process-data :before ((data t))
  (format t "Preparing to process data: ~a~%" data))

; define a integer specific before method
(defmethod process-data :before ((data integer))
  (format t "Integer specific preparation: ~a~%" data))

; integer based generic function
(defmethod process-data ((data integer))
  (format t "Processing integer: ~a, result: ~a~%" data (* data 2)))

; string based generic function
(defmethod process-data ((data string))
  (format t "Processing string: ~a, result: ~a~%" data (concatenate 'string data " processed")))

; call integer based function
(format t "~a~%" (process-data 10))

; call string based function
(format t "~a~%" (process-data "test"))

Output

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

Integer specific preparation: 10
Preparing to process data: 10
Processing integer: 10, result: 20
NIL
Preparing to process data: test
Processing string: test, result: test processed
NIL

Explanation

When a generic function is called , the before function is called before as per the most-specific-first order

  • When process-data 10 called, then integer specific :before method is executed before it.

  • Integer specific preparation: 10 is printed.

  • Now generic :before method is called.

  • Preparing to process data: 10 is printed.

  • Finally integer based process-data is called.

  • Processing integer: 10, result: 20 is printed.

Advertisements