Lisp - :after Method Combination



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

  • To add functionality after execution of primary method.

  • Log or trace method calls.

  • To perform finishing work.

Defining :after function

An :after function is defined using following syntax

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

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

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

Example - :after Function

Following is the complete example of a :after function.

main.lisp

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

; define a generic after method
(defmethod process-data :after ((data t))
  (format t "Data processed: ~a~%" data))

; define a integer specific after method
(defmethod process-data :after ((data integer))
  (format t "Integer processing completed: ~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 −

Processing integer: 10, result: 20
Data processed: 10
Integer processing completed: 10
NIL
Processing string: test, result: test processed
Data processed: test
NIL

Explanation

When a generic function is called , the after function is called after as per the most-specific-last order

  • When process-data 10 called, then integer based generic method is called.

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

  • Now generic :after method is called.

  • Data processed: 10 is printed.

  • Finally integer based :after is called.

  • Integer processing completed: 10 is printed.

  • Same is repeated for string.

Advertisements