2

我正在为方案中的方案创建一个评估器,我希望它具有的功能之一是地图。但是,我发现的所有 map 定义都不允许多个列表。例如:

(define (my-map proc lis)
   (cond ((null? lis)
          '())
         ((pair? lis)
          (cons (proc (car lis))
                (my-map proc (cdr lis))))))

这个 map 的定义是“不完整的”,因为例如,你不能像这样添加 2 个数字列表(它只允许一个列表作为参数):

(my-map + '(1 2 3) '(4 5 6))

如何修改上述地图定义以允许任意数量的列表?

4

3 回答 3

4

您可以根据仅适用于一个列表multi-map的过程定义一个适用于多个列表的one-map过程(这就是您的my-map过程正在做的事情,尽管第二个条件有点不寻常)。

假设所有列表的长度相同,并且至少有一个列表作为参数传递给multi-map

(define (one-map proc lst)
  (if (null? lst)
      '()
      (cons (proc (car lst))
            (one-map proc (cdr lst)))))

(define (multi-map proc . lst)
  (if (null? (car lst))
      '()
      (cons (apply proc (one-map car lst))
            (apply multi-map proc (one-map cdr lst)))))

例如:

(multi-map + '(1 2 3) '(4 5 6) '(7 8 9))
=> '(12 15 18)
于 2013-07-14T02:30:31.367 回答
1

好吧,允许my-map获取多个列表的语法很简单(define (my-map mapper lst1 . lsts) ...)

但这不是你真正要问的,不是吗?一般的实现方式如下:

  1. 查看是否有任何列表为空。如果是,则返回空列表。
  2. 收集每个列表的第一个元素,并将它们作为参数传递给映射器。
  3. my-map使用每个列表的其余部分,使用对的递归调用来反对该映射器调用的结果。

步骤 2 和 3 可能会使用单列表版本的map.

于 2013-07-14T02:21:03.897 回答
1

map是一个库过程。例如。如果您实现定义,则不需要在评估器中将其作为原语实现。然而,它是在SRFI-1 列表库中定义的,它带有一个参考实现,并且根据您的评估器所拥有的(延续、多个值、宏),您可能需要对其进行一些编辑或实施上述限制以使其工作。映射的代码:

(define (map-in-order f lis1 . lists)
  (check-arg procedure? f map-in-order)
  (if (pair? lists)
      (let recur ((lists (cons lis1 lists)))
        (receive (cars cdrs) (%cars+cdrs lists)
                 (if (pair? cars)
                     (let ((x (apply f cars)))  ; Do head first,
                       (cons x (recur cdrs)))   ; then tail.
                     '())))

      ;; Fast path.
      (let recur ((lis lis1))
        (if (null-list? lis) lis
            (let ((tail (cdr lis))
                  (x (f (car lis))))      ; Do head first,
              (cons x (recur tail)))))))  ; then tail.
于 2013-07-17T15:08:29.380 回答