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 がないと作ったリストを取り出せない。