;;; amb.rkt ;;; ============ Implementation minimale de amb ==================== ;;; d'apres Dorai Sitaram (Teach Yourself Scheme in Fixnum Days) #lang racket (provide amb initialize-amb-fail! assert) (define amb-fail #f) ; la continuation de backtrack courante (define (initialize-amb-fail!) (set! amb-fail (lambda () (error "amb : no more solution !")))) ; La fonction ci-dessous est necessaire en Racket car un module ne peut pas ; modifier une variable d'un autre module ! ; Meme si le set! est introduit par une macro-expansion comme dans la macro amb. (define (set-amb-fail! new-fail) (set! amb-fail new-fail)) (define-syntax amb (syntax-rules () ((amb x ...) (let ((old-amb-fail amb-fail)) (call/cc (lambda (sk) (call/cc (lambda (fk) (set-amb-fail! fk) (sk x))) ... (old-amb-fail))))))) (define (assert bool) (when (not bool) (amb))) (initialize-amb-fail!) ;;; un petit test ;(let ((x (amb 1 2)) (y (amb 3 4))) ; (assert (= (+ x y) 5)) ; (list x y)) ; ;(amb) ;(amb)