Heres a real simple implementation. Given A in the range of 0 32, B in the range of 0 64, and C in the range of 0 128, it collects every combination of these 3 values that solves =128. Currently =128 is set to (= 128 (+ (* a b) c)), but could be changed.
(defmacro awhen (clause &rest body) `(let ((it ,clause)) (when it ,@body)))
(defvar *fail-stack*)
(defvar *results*)
(defun evaluate () (setf *results* nil) (tagbody :start (awhen (pop *fail-stack*) (funcall it) (go :start))) *results*)
(defun apply-one-of (k start length)
(assert (>= length 0))
(if (zerop length)
(funcall k start)
(progn (push #'(lambda () (apply-one-of k start (1- length))) *fail-stack*)
(funcall k (+ start (1- length))))))
(defun =128? (a b c) (= 128 (+ (* a b) c)))
(setf *fail-stack*
(list #'(lambda () (apply-one-of
#'(lambda (a) (apply-one-of
#'(lambda (b) (apply-one-of
#'(lambda (c) (when (=128? a b c) (push (list a b c) *results*)))
0 128))
0 64))
0 32))))
(evaluate)
This particular problem could be more easily solved with straight forward loops, but it illustrates how backtracking is implemented. Basically, you have this fail stack of functions to execute. Take the top one and run it. It could potentially put more fail functions on the fail-stack.
The next trick is generating the functions. Generally you want functions that continue from where you currently are, but with a different value. This is where continuations come in. I've written my 'apply-one-of' in a continuation-passing style, but you could use macros to assist the conversion. This example was so simple I could name my continuations like so, most backtracking computations are not so simple.
(defun step-c (c) (when (=128? *a* *b* c) (push (list *a* *b* c) *results*)))
(defun step-b (b) (setf *b* b) (apply-one-of #'step-c 0 128))
(defun step-a (a) (setf *a* a) (apply-one-of #'step-b 0 64))
(defun solve () (apply-one-of #'step-a 0 32))
(setf *fail-stack* (list #'solve))
(evaluate)
Need an online wiki database? My Lisp startup
http://www.formlis.com combines a wiki with forms and reports.