函数对应this定义笛卡尔积。
参数中的点. 表示lists 将收集所有参数(在一个列表中),无论传入多少。
如何调用这样的函数?使用apply。它使用列表中的项目作为参数应用函数:(apply f (list x-1 ... x-n)) = (f x-1 ... x-n)
foldr 只是对列表自然递归的抽象
; my-foldr : [X Y] [X Y -> Y] Y [List-of X] -> Y
; applies fun from right to left to each item in lx and base
(define (my-foldr combine base lx)
(cond [(empty? lx) base]
[else (combine (first lx) (my-foldr func base (rest lx)))]))
应用 1)、2) 和 3) 的简化并将 foldr 中的“组合”功能转换为单独的帮助器:
(define (cartesian-product2 . lists)
(cond [(empty? lists) '(())]
[else (combine-cartesian (first lists)
(apply cartesian-product2 (rest lists)))]))
(define (combine-cartesian fst cart-rst)
(append-map (lambda (x)
(map (lambda (y)
(cons x y))
cart-rst))
fst))
(cartesian-product2 '(1 2 3) '(5 6))
让我们想想combine-cartesian 做了什么:它只是将 n-1-ary 笛卡尔积转换为 n-ary 笛卡尔积。
我们想要:
(cartesian-product '(1 2) '(3 4) '(5 6))
; =
; '((1 3 5) (1 3 6) (1 4 5) (1 4 6) (2 3 5) (2 3 6) (2 4 5) (2 4 6))
我们有(first lists) = '(1 2) 和递归调用的结果(归纳):
(cartesian-product '(3 4) '(5 6))
; =
; '((3 5) (3 6) (4 5) (4 6))
要从我们拥有的(递归的结果)到我们想要的,我们需要将 cons 1 加到每个元素上,将 cons 2 加到每个元素上,并附加这些列表。概括这一点,我们可以使用嵌套循环对 combine 函数进行更简单的重构:
(define (combine-cartesian fst cart)
(apply append
(for/list ([elem-fst fst])
(for/list ([elem-cart cart])
(cons elem-fst elem-cart)))))
为了添加一个维度,我们将(first lists) 的每个元素转换为其余的笛卡尔积的每个元素。
伪代码:
cartesian product <- takes in 0 or more lists to compute the set of all
ordered pairs
- cartesian product of no list is a list containing an empty list.
- otherwise: take the cartesian product of all but one list
and add each element of that one list to every
element of the cartesian product and put all
those lists together.