(define (lst-double-helper lst acc)
(if (empty? list)
acc
(lst-double-helper (rest lst) (cons (* (first lst) 2) acc))))
(define (lst-double lst)
(lst-double-helper lst '()))
我觉得我做对了。但这给我一个错误
(lst-double '(1,2,3))
*: contract violation
expected: number?
given: ',2
argument position: 1st
other arguments...:
为什么期望第二个参数是数字?
答案 0 :(得分:1)
一些评论:
lst
,而不是list
。reverse
才能恢复原始顺序进行上述更改后,它可以按预期工作:
(define (lst-double-helper lst acc)
(if (empty? lst) ; parameter is called `lst`
acc
(lst-double-helper (rest lst) (cons (* (first lst) 2) acc))))
(define (lst-double lst)
(reverse ; required to restore original order
(lst-double-helper lst '())))
(lst-double '(1 2 3)) ; use spaces to separate elements
=> '(2 4 6)
请注意,遍历输入列表并cons
使用其元素以构建输出列表的尾部递归解决方案将必然颠倒输入列表中元素的顺序。没关系,最后做reverse
是正常的。避免在最后反转元素的可能替代方法是在开始时反转输入列表或编写非尾随追溯的解决方案。
答案 1 :(得分:1)
一种这样的方法是通过使用延续传递样式。在这里,我们添加了一个名为return
的参数,该参数有效地编码了带有lambda的类似返回的行为。 double
现在接受两个参数:要加倍的列表xs
和结果的延续return
–
(define (double xs return)
(if (empty? xs)
(return empty)
(double (cdr xs)
(lambda (result)
(return (cons (* 2 (car xs))
result))))))
例如,将double
应用于'(1 2 3)
列表的结果发送到print
(double '(1 2 3) print)
;; '(2 4 6)
;; => #<void>
double
的计算结果为最终延续计算的结果;在这种情况下,print
的值为#<void>
。我们可以使用identity
函数来有效地获取价值–
(double '(1 2 3) identity)
;; => '(2 4 6)
使用球拍,您可以轻松地指定默认参数,因此我们可以将double
修改为使用identity
作为默认延续
(define (double xs (return identity))
;; ...
)
这种样式导致便捷的程序可以同时在两种调用样式下工作:连续传递样式–
(double '(10 11 12) print)
;; '(20 22 24)
;; => #<void>
(double '(10 11 12) length)
;; => 3
(double '(10 11 12) car)
;; => 20
(double '(10 11 12) cdr)
;; => '(22 24)
... 或直接样式,使用默认的identity
延续
(print (double '(10 11 12)))
;; '(20 22 24)
(length (double '(10 11 12)))
;; => 3
(car (double '(10 11 12)))
;; => 20
(cdr (double '(10 11 12)))
;; => '(22 24)
答案 2 :(得分:0)
使用地图。
(地图(lambda(a)(* a 2))'(1 2 3))
答案 3 :(得分:0)
对于嵌套列表:
(define (atom? x)
(and (not (null? x))
(not (pair? x))))
(define (lst-double-helper lst acc)
(cond ((empty? lst) acc)
((atom? (car lst)) (lst-double-helper (rest lst) (cons (* (first lst) 2) acc)))
(else (lst-double-helper (rest lst) (cons (lst-double (first lst))
acc) ))))
(define (lst-double lst)
(reverse ; required to restore original order
(lst-double-helper lst '())))
但是实际上使该函数尾部递归有点没有意义,
因为正如@simmone所述,map
会做到
(define (list-doubler lst)
(map (lambda (x) (* 2 x)) lst))
(list-doubler '(1 2 3))
;; '(2 4 6)