Recursion 自定义地图功能-它是如何工作的?

Recursion 自定义地图功能-它是如何工作的?,recursion,scheme,variadic-functions,map-function,Recursion,Scheme,Variadic Functions,Map Function,很抱歉主题标题不清楚。 我在Scheme中有这个函数,它是map函数的自定义实现。它工作得很好,但我在试图理解它时迷失了方向 (define (my-map proc . ls) (letrec ((iter (lambda (proc ls0) (if (null? ls0) '() (cons (proc (car ls0))

很抱歉主题标题不清楚。

我在Scheme中有这个函数,它是
map
函数的自定义实现。它工作得很好,但我在试图理解它时迷失了方向

(define (my-map proc . ls)
  (letrec ((iter (lambda (proc ls0)
                   (if (null? ls0)
                       '()
                       (cons (proc (car ls0)) 
                             (iter proc (cdr ls0))))))
           (map-rec (lambda (proc ls0)
                     (if (memq '() ls0)
                         '()
                         (cons (apply proc (iter car ls0)) 
                               (map-rec proc (iter cdr ls0)))))))
    (map-rec proc ls)))
问题在于
cons(proc(car ls0))
。如果我是正确的,当将
(1 2 3)(4 5 6)
传递到
ls
参数时,它的实际值将是
((1 2 3)(4 5 6))
。因此,
map rec
中的
iter car ls0
将通过
(1 2 3)
iter
。因此,
iter
中的
proc(carls0)
将具有以下形式:
(car(car(1233))
,但这是不可能的,对吗


我知道我的想法在某个地方有缺陷,但我不知道在哪里。

这里有一种方法可以理解这个过程:

  • iter
    辅助程序与
    map
    相同,但在单个列表上操作
  • map rec
    帮助程序概括了
    iter
    ,处理列表列表,当至少一个列表为空时停止
  • 本部分:
    (应用程序(iter car ls0))
    对每个列表的第一个元素应用程序;调用
    iter
    将创建
    car
    部分列表的列表
  • 这一部分:
    (map rec proc(iter-cdr-ls0))
    同时推进所有列表的递归;调用
    iter
    将创建
    cdr
    部分列表的列表
也许重新命名程序会让事情变得更清楚。下面是一个完全等效的实现,明确说明了
map one
在单个列表上运行,而
map many
在列表上运行的事实:

(define (map-one proc lst)  ; previously known as `iter`
  (if (null? lst)
      '()
      (cons (proc (car lst))
            (map-one proc (cdr lst)))))

(define (map-many proc lst) ; previously known as `map-rec`
  (if (memq '() lst)
      '()
      (cons (apply proc (map-one car lst))
            (map-many proc (map-one cdr lst)))))

(define (my-map proc . lst) ; variadic version of `map-many`
  (map-many proc lst))
(map-one car '((1 4 5) (2 6 7) (3 8 9)))
=> '(1 2 3)
它的工作原理与原始的
我的地图一样

(my-map + '(1 2 3) '(4 5 6) '(7 8 9))
=> '(12 15 18)
您可以检查
map one
是否确实是在单个列表上工作的
map

(map-one (lambda (x) (* x x))
         '(1 2 3 4 5))
=> '(1 4 9 16 25)
查看列表列表上的
(映射一辆车lst)
效果:

(define (map-one proc lst)  ; previously known as `iter`
  (if (null? lst)
      '()
      (cons (proc (car lst))
            (map-one proc (cdr lst)))))

(define (map-many proc lst) ; previously known as `map-rec`
  (if (memq '() lst)
      '()
      (cons (apply proc (map-one car lst))
            (map-many proc (map-one cdr lst)))))

(define (my-map proc . lst) ; variadic version of `map-many`
  (map-many proc lst))
(map-one car '((1 4 5) (2 6 7) (3 8 9)))
=> '(1 2 3)
同样,请参见
(映射一个cdr lst)
的工作原理:

(map-one cdr '((1 4 5) (2 6 7) (3 8 9)))
=> '((4 5) (6 7) (8 9))

非常感谢。我不知道为什么,但我认为
(映射一辆车lst)
会将列表(即第一个列表)中的
传递到
映射一辆车
,但它当然会传递整个过程,所以
(车(车lst))
将返回内部列表的第一项。您可能还感兴趣的是,其中讨论了如何根据只接受单个列表的
map
实现接受多个列表的
map
。感谢链接,我一定会查找它。