产品作为输入参数?

时间:2014-02-03 17:25:33

标签: scheme racket

在lisp / scheme中,是否有使用 set product 作为函数输入的任何形式? map 表单使用 n 长度相等的列表来表示需要 n 参数的函数。有时,我们需要来自一组集的乘积的参数。例如:

(pmap (λ (d p) foo)
           A B)

此处,列表 A 可能与 B 的长度不同,而 pmap 会为 A的产品的每个元素提供 B lambda 表达式。

方案/球拍 *的表单可以完成这项工作:

(for* ([x '(0 2 4)]
       [y '(1 3 5)])
      ((λ (d p)
           (printf "(~a, ~a)\n" d p))
       x y))

输出:

(0, 1)
(0, 3)
(0, 5)
(2, 1)
(2, 3)
(2, 5)
(4, 1)
(4, 3)
(4, 5)

我想知道在方案中是否存在类似于地图弃放的其他方式。

2 个答案:

答案 0 :(得分:1)

据我所知,标准中没有这样的东西。然而,写一个不是问题。

有关有用列表函数的概述,我可以推荐srfi1,除了map和fold之外,它还提供了许多有用的操作。

http://srfi.schemers.org/srfi-1/srfi-1.html

答案 1 :(得分:0)

我写了pmap的以下实现。它仅使用conscarcdrnull?applymapreverse,并支持任意数量的像map这样的论点确实如此。

(define (pmap f . xs) 
  (define (carry a xs ys then)
    (if (and (not (null? ys)) (null? (car ys)))
        '()
        (if (null? xs) 
            (then (reverse a))
            (if (null? (car xs))
                (if (null? (cdr xs)) 
                    '()
                    (carry (cons (car ys) a) (cons (cdr (car (cdr xs))) (cdr (cdr xs))) (cdr ys) then))
                (carry (cons (car xs) a) (cdr xs) (cdr ys) then)))))

  (define (pmap-helper f xs ys)
    (carry '() xs ys 
           (lambda (xs)
             (cons (apply f (map car xs)) 
                   (pmap-helper f (cons (cdr (car xs)) (cdr xs)) ys)))))

  (pmap-helper f xs xs))

(display (pmap list '(0 2 4) '(1 3 5))) (newline)
;((0 1) (2 1) (4 1) (0 3) (2 3) (4 3) (0 5) (2 5) (4 5))

唯一的区别是早期的列表比后面的列表迭代得更快,而你的例子则相反。可以修改此pmap来执行此操作:

(define (pmap f . xs) 
  (define (carry a xs ys then)
    (if (and (not (null? ys)) (null? (car ys)))
        '()
        (if (null? xs) 
            (then (reverse a))
            (if (null? (car xs))
                (if (null? (cdr xs)) 
                    '()
                    (carry (cons (car ys) a) (cons (cdr (car (cdr xs))) (cdr (cdr xs))) (cdr ys) then))
                (carry (cons (car xs) a) (cdr xs) (cdr ys) then)))))

  (define (pmap-helper f xs ys)
    (carry '() xs ys 
           (lambda (xs)
             (cons (apply f (reverse (map car xs))) 
                   (pmap-helper f (cons (cdr (car xs)) (cdr xs)) ys)))))

  (let ((xs (reverse xs)))
    (pmap-helper f xs xs)))

(display (pmap list '(0 2 4) '(1 3 5))) (newline)
; ((0 1) (0 3) (0 5) (2 1) (2 3) (2 5) (4 1) (4 3) (4 5))