正如您在下面的示例中所看到的,Scheme中的map函数是可变参数函数。
> (map (lambda (number1 number2)
(+ number1 number2))
'(1 2 3 4)
'(10 100 1000 10000))
'(11 102 1003 10004)
我想实现这个可变参数选项,但我只是成功找到了两个参数map的实现:
(define (map f lst)
(if (null? lst)
'()
(cons (f (car lst)) (map f (cdr lst)))))
有人可以帮我实现可变参数映射函数吗?
答案 0 :(得分:9)
在Scheme中,您可以将可变参数函数编写为(lambda x ...)
,在这种情况下x
绑定到整个参数列表,或者使用不正确的lambda列表,例如{{1} },它将至少三个参数,并将(lambda (a b c . ds) ...)
绑定到剩余参数的列表中。那么你要编写的代码就像(我在R5RS Scheme中编写):
ds
这可以按预期工作:
(define (my-map function list1 . more-lists)
(define (some? function list)
;; returns #f if (function x) returns #t for
;; some x in the list
(and (pair? list)
(or (function (car list))
(some? function (cdr list)))))
(define (map1 function list)
;; non-variadic map. Returns a list whose elements are
;; the result of calling function with corresponding
;; elements of list
(if (null? list)
'()
(cons (function (car list))
(map1 function (cdr list)))))
;; Variadic map implementation terminates
;; when any of the argument lists is empty
(let ((lists (cons list1 more-lists)))
(if (some? null? lists)
'()
(cons (apply function (map1 car lists))
(apply my-map function (map1 cdr lists))))))
请注意,为了使这项工作,我们需要一个非变量(my-map + '(0 2 5) '(1 2 3))
;=> (1 4 8)
(此处称为map
),以便map1
获取参数列表以调用(map1 car lists)
使用和function
获取列表的休止符以进行递归。要编写可变参数(map1 cdr lists)
(此处称为map
),您需要实现非变量my-map
。
答案 1 :(得分:2)
您已经得到了答案,但请注意,有一个语法关键字case-lambda
可让您明确说明在数字或参数变化时使用的过程。你会这样使用它:
(define my-map
(case-lambda
((func list) …)
((func list1 list2) …)
(…)
((func . lists) …)))
这样,您可以优化对不同参数计数的处理。 case-lambda
生成一个“包裹lambda”,基本上看起来像这样(但可能会更有效地编译):
(define my-map
(lambda args ;; illustration only, implementations vary.
(apply (let ((len (length args)))
(cond ((= 2 len) (lambda (func list) …))
…))
args)))