The interface functions are created in the back-end and always refer
to lexical variables, so I need to return closures. However, there are
several strategies possible.
a) Return a multiple value list of closures and bind them in the front-
end to call them via funcall
b) Return a structure containing these closures and also call them via
funcall
c) export them via the package definition and create them as named
closures in the following fashion
(defun create-closures ()
(let ((a 0))
(values
(defun closure-up ()
(incf a))
(defun closure-down ()
(decf a)))))
Maybe I should even write some glue ? In the current case the front-
end loads the back-end, but maybe I should have a third program which
initialises the back-end, and then initialise the front-end using the
return value from the back-end ?
Regards,
Jurgen
Closures are equivalent to objects.
Why don't you use normal CLOS objects, with classes and subclasses?
(defclass counter ()
((a :initform 0)))
(defmethod counter-up ((self counter))
(incf (slot-value self 'a)))
(defmethod counter-down ((self counter))
(decf (slot-value self 'a)))
(defun create-counter ()
(make-instance 'counter))
(let ((c (create-counter)))
(counter-up c)
(counter-down c))
Then you can easily define "back-end" counters:
(defclass remote-counter (counter)
((host :initform "localhost" :initarg :host :reader host)
(login :initform "counter" :initarg :login :reader login)
(file :initform "~/counter" :initarg :file :reader file)))
(defmethod gen-command ((self remote-counter) operator)
(format nil "ssh \"~A@~A\" bash -c 'counter=$(cat ~S);counter=$(( $counter ~A 1 ));echo $counter>~2:*~S'"
(login self) (host self) (file self) operator))
(defmethod counter-up ((self remote-counter))
(ext:shell (gen-command self "+")))
(defmethod counter-down ((self remote-counter))
(ext:shell (gen-command self "-")))
and write create-counter to select the right backend:
(defun create-counter ()
(ecase *backend*
((:remote)
(make-instance 'remote-counter :host *remote-host* :login *remote-login* :file *remote-file*))
((:local)
(make-instance 'counter))))
For a more complete example, have a look at the sources of swank.
--
__Pascal Bourguignon__