(define (cart . lists)
(cond ((null? lists) '())
((= (length lists) 1) (map list (first lists)))
(else
(append-map (lambda(x)
(map (lambda(y) (cons y x))
(first lists)))
(apply cart (rest lists))))))
(define (numbers n)
(define (reversed-numbers n)
(if (= n 0)
'()
`(,n . ,(reversed-numbers (- n 1)))))
(reverse (reversed-numbers n)))
(define (gen-truth n vals)
(apply cart (map (lambda(x) list vals) (numbers n))))
(gen-truth 2 '(#t #f)) returns: '((#t #t) (#f #t) (#t #f) (#f #f))
(define and-l (lambda x
(if (null? x)
#t
(if (car x) (apply and-l (cdr x)) #f))))
为什么:(apply map and-l (gen-truth 2 '(#t #f)))
返回'(#f #f)
?我希望它为每个包含成对布尔值的子表达式返回一个布尔值。
第一个问题是and-l
过程被破坏。在此,x
在传递到过程主体之前被放入列表中。考虑:
scratch.rkt> (define bad-proc (lambda x x))
scratch.rkt> (bad-proc '(#t #f))
'((#t #f))
and-l
过程应该测试一个列表是否包含所有真值,而传递给该过程主体的一个确实包含:
scratch.rkt> (and-l-bad '(#t #f))
#t
scratch.rkt> (and-l-bad '(#f #f))
#t
scratch.rkt> (and-l-bad '(#t #t))
#t
这里是and-l
的正确版本;注意,不需要apply
:
(define and-l
(lambda (x)
(if (null? x)
#t
(and (car x) (and-l (cdr x))))))
测试新过程:
scratch.rkt> (and-l '(#t #f))
#f
scratch.rkt> (and-l '(#f #f))
#f
scratch.rkt> (and-l '(#t #t))
#t
现在and-l
可以正常工作,我们将注意力转向:
(apply map and-l (gen-truth 2 '(#t #f)))
同样,这里不需要apply
。在这里甚至没有意义(apply map and-l ;....)
。 apply
过程将过程和列表作为参数,并将列表的元素用作过程的参数。因此,(apply + '(1 2 3 4))
等效于(+ 1 2 3 4)
。在当前情况下不需要此功能;所有需要的是map
将and-l
应用于gen-truth
返回的列表中的每个布尔列表:
scratch.rkt> (gen-truth 2 '(#t #f))
'((#t #t) (#f #t) (#t #f) (#f #f))
scratch.rkt> (map and-l (gen-truth 2 '(#t #f)))
'(#t #f #f #f)