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

问题描述:

我为不清楚的主题标题道歉。自定义地图功能 - 它是如何工作的?

我在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))。因此iter car ls0map-rec将通过(1 2 3)iter。因此proc (car ls0)iter将形式:(car (car (1 2 3))),但这是不可能的,对吧?

我知道我的思想在某处存在缺陷,但我无法弄清楚在哪里。

+1

您还可能有兴趣在(HTTP [在方案可变参数地图功能的实现]: //*.com/q/21629203/1281433),其中讨论了如何实现'map',该'map'接受只接受单个列表的'map'方面的多个列表。 –

+0

感谢您的链接,我一定会查找它。 – Kapol

下面就来了解程序的一种方法:

  • iter帮手相同map,而是一个单独的列表上运行。
  • map-rec辅助概括iter,工作列表的列表,停止时的列表中的至少一个是空的
  • 这部分:(apply proc (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)) 

它的工作原理就像当初my-map

(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) 

见名单列表上的(map-one car lst)效果:

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

同样,看看如何(map-one cdr lst)作品:

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

谢谢。我不知道为什么,但我认为'(地图一汽车)'会将列表列表(即第一个列表)的'car'传递给map-one,但它会当然,通过整个事情,所以'(car(car lst))'将返回内部列表中的第一项。 – Kapol