"Inversion of control" is widely used in Lisp. It is absolutely simple, because functions and closures are first-class objects.
Injection injection is trivial. Classes and functions can be configured using characters and classes of the first class.
Usually, you donโt need the โinfrastructureโ for IoC or DI in Common Lisp, since the built-in functionality for configuring and parameterizing applications and libraries.
"first class" means that something can be stored in variables, passed as arguments, or returned as results.
In a language like Common Lisp, functions and classes are first-class objects. Plus, for decoupling using late binding, you can use characters as their names instead. Generic Lisp An object system knows meta classes and characters as names for classes. Even common functions and methods are objects and have metaclasses.
If concurrent-secure-server
is a class, and default-response
is a function, you can do, for example:
(make-instance 'web-services :server-class 'concurrent-secure-server :default-response-function 'default-reponse)
Above, the symbol is used as the name for the class and function. If the function receives a new version, the web service may later call a new one.
As an alternative:
(make-instance 'web-services :server-class (find-class 'concurrent-secure-server) :default-response-function
In the above case, we pass a class object and an object to a function.
In Common Lisp, program modules can have global variables that you can set with the correct information:
(defvar *default-server-class* 'concurrent-secure-server)
Alternatively, you can install them in the slots as shown below.
(defclass server-object () ((default-response-function :initarg :default-response-function :initform *server-default-response-function*))) (defvar *my-server* (make-instance 'server-object :default-response-function 'my-default-response-function))
You can even create objects and then change their class in the configuration phase. The generic Lisp Object System allows you to modify classes and update existing objects.
If you create an instance, you can be as flexible as you want:
- you can go to class
- you can pass arguments
Like this:
(let ((my-class 'foo-class) (my-args `(:response-function ',*some-reponse-function))) (apply #'make-instance my-class my-args))
Sometimes you see Lisp libraries that compute such parameter lists at runtime.
Another where you can customize Lisp applications at runtime is with common functions. Common functions allow: before,: after, and: around methods - they even allow you to use your own calling schemes. Thus, using native classes inheriting from other classes and mixin classes, the general function is reconfigured. It looks like you have the basic mechanisms built into Aspect-oriented programming.
For people interested in these more advanced object-oriented concepts, there is some literature from Xerox PARC where these problems have been investigated when creating CLOS. Then it was called "Open implementation":
http://www2.parc.com/csl/groups/sda/publications.shtml
In the Open Implementation approach, modules allow their customers to individually control their own module implementation strategy. This allows the client to adapt the implementation strategy of the module to better meet their needs, effectively making the module more reusable and the client code simpler. This control is provided to customers through a well-designed support interface.
One thing you don't need: XML. Generic Lisp is its own configuration language. Writing extensions to simplify the configuration can be done, for example, using macros. Downloading these configurations can be easily done using LOAD
.