0

我希望创建一个可以将两个功能合二为一的功能。给定gand f,它应该创建一个函数h,将 的输出f作为输入提供给g。这是我的结果:

(define (compose g f)
    (lambda (.args)
        (g (apply f (if (atom? .args) (list .args) .args)))))

以下代码段适用于compose.

(display ((compose add1 add1) 3))

但是,我无法弄清楚为什么下面的示例不起作用。我提供了下面的错误消息,我使用的是 Chez Scheme 9.5.2。这里的错误可能与 的可变参数性质有关compose,但这只是一个想法。有谁知道为什么我的第二次测试没有按预期工作?

(define (reduce f lst seed)
    (if (null? lst) seed
        (f (car lst) (reduce f (cdr lst) seed))))

(define product-of-incremented-list
    (compose
        (lambda (lst) (reduce * lst 1))
        (lambda (lst) (map add1 lst))))

(display (product-of-incremented-list '(3 4 5)))
; I was expecting 120, because (3 4 5) -> (4 5 6) and (4 5 6) -> 120
; I'm getting an error instead:
; Exception: incorrect number of arguments to #<procedure at compose.scm:285>
4

1 回答 1

1

您试图用来.args表示“参数列表”,可能与 类比(lambda (x . more) ...),但这是不正确的。.args只是一个和其他符号一样的符号,所以您编写了一个函数,它接受一个名为.args. 然后,当您发现您的论点是一个列表时,您(apply f '(3 4 5)). 但是您使用的 lambdaf不需要三个参数,它需要一个列表参数。因此错误。

相反,说“参数列表”的方式是

(lambda args
  ...)

一般来说,你在 lambda 之后写的是如何对待输入参数列表。如果你放一个这样的列表(x y),那么参数列表应该是两个组件,x并且y. 对于(x . more),第一个元素被命名x,然后列表的其余部分被命名more。如果您只想要列表原样,您只需给它一个名称:here, args.

您的第二个问题是检查参数是列表还是原子。这很愚蠢:您可以确定它始终是一个列表,因为您没有分解输入参数。所以,

(define (compose f g)
  (lambda args
    (f (apply g args))))
于 2020-11-12T19:09:54.597 回答