在课堂(方案)中,我们最近了解了允许函数接受任意数量参数的语法,例如;
(define len
(lambda args
(length args)))
>(len 1 2 3)
3
与首先将参数简单地作为单个列表传递相比,使用这种形式有什么优势?您甚至如何在程序中(而不是在命令行上)将参数传递给这些类型的函数?有没有办法制作一个返回一系列未包含在列表中的值的过程?
一个非常有用的例子是
(define (list . elements) elements)
; or
(define list (lambda elements elements))
对于自然是n元函数的函数,可变参数函数也很方便。例如,如果你已经有一个二进制加法函数add2
,你可以做
(define + (lambda addends (foldl add2 0 addends)))
; or
(define (+ . addends) (foldl add2 0 addends))
除了像这样称呼这些
(+ 1 2 3)
;=> 6
apply
当您已经在列表中有参数时,您也可以使用:
(apply + '(1 2 3))
;=> 6
这样做的一个好处是更容易编写使用不同参数约定的函数。我不知道这在 Scheme 中是否特别常见,但您可以使用它来获取关键字/命名参数。例如,而不是定义
(define (subseq lst start end) ...)
你总是需要提供开始和结束参数的地方,你可以这样做
(define (subseq lst . args) ...)
所以这lst
总是必要的,但 args 可以或不可以包含开始和结束参数。您可以使用它来实现默认值。例如,
(subseq lst 'start 3 'end 6) ; specify both expllicitly
(subseq lst 'end 6) ; default value for start, e.g., 0
(subseq lst 'start 4) ; default value of end, e.g., length of list
(subseq lst) ; default for both, copy the list
您必须编写代码来提取指定值或默认值,但这并不难。
至于返回多个值,您可以使用恰当命名的返回多个值values
:
(values 1 2 3)
;=> 1
;=> 2
;=> 3
但这实际上与带有任意数量参数的函数无关,因为它们与列表相关联,并且与列表values
无关。
假设您有以下两个“len”函数:
(define len1
(lambda args (length args)))
(define len2
(lambda (lst) (length lst)))
您可以将这些调用为:
> (len1 1 2 3)
3
> (len2 (list 1 2 3)
3
如您所见,没有太大区别。如果len2
您创建了列表;len1
在编译器创建列表的情况下。可以说编译器可能会更高效一些。
让我们假设您已经有一个想要获取长度的列表。对于这两个你会使用:
> (define l '(1 2 3))
> (apply len1 l)
3
> (len2 l)
3
; note
> (len1 l)
1
该apply
函数将一个列表作为其第二个参数,并将列表元素作为参数“呈现”给它的第一个参数(len1
在本例中)。
如果您不想返回列表但确实想返回多个值,您将values
用作
(define my-return-3-values-function
(lambda (a b c)
(values a b c)))
values
是的,您可以使用该过程返回多个值,并且可以使用apply
. 但是您的课程可能还没有教授这些概念。:-)