Ex. 4.53
結構準備がたいへん。
amb評価器も少し変更 (define primitive-procedures (list (list 'car car) ... (list 'remainder remainder) ;; prime?で使うので ...
amb評価器に事前に喰わせておくソース
;;; Amb-Eval input: ;;p.246 (define (require p) (if (not p) (amb))) ;;p.245 (define (an-element-of items) (require (not (null? items))) (amb (car items) (an-element-of (cdr items)))) ;; p.28 (define (divides? a b) (= (remainder b a) 0)) ;;p.15 (define (square x) (* x x)) ;;p.28 (define (find-divisor n test-divisor) (cond ((> (square test-divisor) n) n) ((divides? test-divisor n) test-divisor) (else (find-divisor n (+ test-divisor 1))))) ;;p.28 (define (smallest-divisor n) (find-divisor n 2)) ;;p.28 (define (prime? n) (= n (smallest-divisor n))) ;;p.245 (define (prime-sum-pair list1 list2) (let ((a (an-element-of list1)) (b (an-element-of list2))) (require (prime? (+ a b))) (list a b)))
これで準備完了。
;;; Amb-Eval input: ;;p260 Ex.4.53 (let ((pairs '())) (if-fail (let ((p (prime-sum-pair '(1 3 5 8) '(20 35 110)))) (permanent-set! pairs (cons p pairs)) (amb)) pairs)) ;;; Starting a new problem ;;; Amb-Eval value: ((8 35) (3 110) (3 20))
いちいち try-again しなくても、ambで探索し発見したアイテムを全部まとめて入手できる。
ambの発見物でリストを作るのは permanent-set! の役目。if-fail がないと作ったリストを取り出せない。