我为不明确的主题标题道歉。
我在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)))
形式,但这是不可能的,对吗?
我知道我的想法在某处有缺陷,但我无法弄清楚在哪里。
答案 0 :(得分:1)
这是理解程序的一种方法:
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))