I want to write code with a multiple user interface backends (textual and graphical for instance), so they are easy to switch. My approach is using CLOS:
(defgeneric draw-user-interface (argument ui)
(:documentation "Present the user interface")
(:method (argument (ui (eql :tui)))
(format t "Textual user interface! (~A)" argument))
(:method (argument (ui (eql :gui)))
(format t "Graphical user interface! (~A)" argument)))
This approach seems OK at a first glance, but it has a few cons. To simplify calls, I define parameter ui-type which will be used in each function call, to simplify switching the backend, but it causes a problem when using higher order functions:
(defparameter *ui-type* :tui
"Preferred user interface type")
(draw-user-interface 3 *ui-type*)
;;; I can't use the following due to the `ui' argument:
;(mapcar #'draw-user-interface '(1 2 3))
;;; Instead I have to write this
(mapcar #'(lambda (arg)
(draw-user-interface arg *ui-type*))
'(1 2 3))
;; or this
(mapcar #'draw-user-interface
'(1 2 3)
(make-list 3 :initial-element *ui-type*))
;; The another approach would be defining a function
(defun draw-user-interface* (argument)
(draw-user-interface argument *ui-type*))
;; and calling mapcar
(mapcar #'draw-user-interface* '(1 2 3))
If such approach is taken, we could name the generic function %draw-user-interface and the wrapper function just draw-user-interface.
Is it valid approach or there is something more straightforward? Question is about providing a different backends for the same functionality, not necessarily the user interface.
The another use case might be a situation, when I have many implementations of the same algorithm (optimized for speed, memory consumption etc.) and I want to switch them in a clean way preserving the interface and the argument types.
To complement other answers, there are two libraries for this use case. Both are inspired in the Magritte Meta Model, you should check it out.
One is descriptions which allows you to define different 'views' of an object. It doesn't use CLOS but Sheeple, a prototype-based object system for CL. An earlier approach is MAO, which is CLOS based. It adds 3 additional slots to the standard slot object. attribute-label, attribute-function, and attribute-value. The function in attribute-function a transforms the slot-value into the final representation, if function is nil the value in attribute-value is used as is. And label is a description of the value, similar to labels in html5 forms.