5

正如您在下面的示例中看到的,Scheme 中的 map 函数是可变参数函数。

> (map (lambda (number1 number2)
     (+ number1 number2))
   '(1 2 3 4)
   '(10 100 1000 10000))
'(11 102 1003 10004)

我想实现这个可变参数选项,但我只成功找到了两个参数映射实现:

(define (map f lst)
   (if (null? lst)
       '()
       (cons (f (car lst)) (map f (cdr lst)))))

有人可以帮我实现可变参数映射功能吗?

4

2 回答 2

10

(lambda x ...)在Scheme中,你可以写x一个(lambda (a b c . ds) ...)可变参数函数ds. 那么,您尝试编写的代码将类似于(我正在使用 R5RS 方案编写):

(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),您已经需要一个非可变参数的实现map

于 2014-02-07T13:43:09.250 回答
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)))
于 2014-02-08T20:12:59.073 回答