自定义地图功能 - 它是如何工作的?
我为不清楚的主题标题道歉。自定义地图功能 - 它是如何工作的?
我在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 ls0
在map-rec
将通过(1 2 3)
到iter
。因此proc (car ls0)
在iter
将形式:(car (car (1 2 3)))
,但这是不可能的,对吧?
我知道我的思想在某处存在缺陷,但我无法弄清楚在哪里。
下面就来了解程序的一种方法:
- 的
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))
谢谢。我不知道为什么,但我认为'(地图一汽车)'会将列表列表(即第一个列表)的'car'传递给map-one,但它会当然,通过整个事情,所以'(car(car lst))'将返回内部列表中的第一项。 – Kapol
您还可能有兴趣在(HTTP [在方案可变参数地图功能的实现]: //*.com/q/21629203/1281433),其中讨论了如何实现'map',该'map'接受只接受单个列表的'map'方面的多个列表。 –
感谢您的链接,我一定会查找它。 – Kapol