一个lambda表达式创建一个函数。在最简单的情况,一个lambda表达式具有的表:
(lambda (arg-id ...) body ...+)
一个具有n个arg-id的lambda表接受n个参数:
> ((lambda (x) x) 1) 1
> ((lambda (x y) (+ x y)) 1 2) 3
> ((lambda (x y) (+ x y)) 1) #<procedure>: arity mismatch;
the expected number of arguments does not match the given
number
expected: 2
given: 1
一个lambda表达式也可以有这种表:
(lambda rest-id body ...+)
也就是说,一个lambda表达式可以有一个没有被圆括号包围的单个rest-id。所得到的函数接受任意数量的参数,并且这个参数放入一个绑定到rest-id的列表:
Examples:
> ((lambda x x) 1 2 3) '(1 2 3)
> ((lambda x x)) '()
> ((lambda x (car x)) 1 2 3) 1
带有一个rest-id的函数经常使用apply函数调用另外的函数,它接受任意数量的参数。
《apply函数》描述apply。
Examples:
(define max-mag (lambda nums (apply max (map magnitude nums)))) > (max 1 -2 0) 1
> (max-mag 1 -2 0) 2
lambda表还支持必需参数与一个rest-id组合:
(lambda (arg-id ...+ . rest-id) body ...+)
这个表的结果是一个函数,它至少需要与arg-id一样多的参数,并且还接受任意数量的附加参数。
Examples:
(define max-mag (lambda (num . nums) (apply max (map magnitude (cons num nums))))) > (max-mag 1 -2 0) 2
> (max-mag) max-mag: arity mismatch;
the expected number of arguments does not match the given
number
expected: at least 1
given: 0
一个rest-id变量有时称为一个rest参数(rest argument),因为它接受函数参数的“剩余(rest)”。
不只是一个标识,一个lambda表中的一个参数(不仅是一个剩余参数)可以用一个标识和一个缺省值指定:
(lambda gen-formals body ...+)
gen-formals = (arg ...) | rest-id | (arg ...+ . rest-id) arg = arg-id | [arg-id default-expr]
表的一个参数[arg-id default-expr]是可选的。当这个参数不在一个应用程序中提供,default-expr产生默认值。default-expr可以引用任何前面的arg-id,并且下面的每个arg-id也必须应该有一个默认值。
Examples:
(define greet (lambda (given [surname "Smith"]) (string-append "Hello, " given " " surname))) > (greet "John") "Hello, John Smith"
> (greet "John" "Doe") "Hello, John Doe"
(define greet (lambda (given [surname (if (equal? given "John") "Doe" "Smith")]) (string-append "Hello, " given " " surname)))
> (greet "John") "Hello, John Doe"
> (greet "Adam") "Hello, Adam Smith"
一个lambda表可以声明一个参数来通过关键字传递,而不是通过位置传递。关键字参数可以与位置参数混合,而且默认值表达式可以提供给两种参数:
《关键字参数》介绍用关键字进行函数调用。
(lambda gen-formals body ...+)
gen-formals = (arg ...) | rest-id | (arg ...+ . rest-id) arg = arg-id | [arg-id default-expr] | arg-keyword arg-id | arg-keyword [arg-id default-expr]
由一个应用程序使用同一个arg-keyword提供一个参数指定为arg-keyword arg-id。关键字的位置——在参数列表中的标识序对与一个应用程序中的参数匹配并不重要,因为它将通过关键字而不是位置与一个参数值匹配。
(define greet (lambda (given #:last surname) (string-append "Hello, " given " " surname)))
> (greet "John" #:last "Smith") "Hello, John Smith"
> (greet #:last "Doe" "John") "Hello, John Doe"
一个arg-keyword [arg-id default-expr]参数指定一个带一个默认值的关键字参数。
Examples:
(define greet (lambda (#:hi [hi "Hello"] given #:last [surname "Smith"]) (string-append hi ", " given " " surname))) > (greet "John") "Hello, John Smith"
> (greet "Karl" #:last "Marx") "Hello, Karl Marx"
> (greet "John" #:hi "Howdy") "Howdy, John Smith"
> (greet "Karl" #:last "Marx" #:hi "Guten Tag") "Guten Tag, Karl Marx"
lambda表不直接支持创建一个接受“rest”关键字的函数。要构造一个接受所有关键字参数的函数,使用make-keyword-procedure函数。这个函数支持make-keyword-procedure通过最先的两个(按位置)参数中的并行列表接受关键字参数,然后来自一个应用程序的所有位置参数作为保留位置参数。
《apply函数》介绍了keyword-apply。
Examples:
(define (trace-wrap f) (make-keyword-procedure (lambda (kws kw-args . rest) (printf "Called with ~s ~s ~s\n" kws kw-args rest) (keyword-apply f kws kw-args rest)))) > ((trace-wrap greet) "John" #:hi "Howdy") Called with (#:hi) ("Howdy") ("John")
"Howdy, John Smith"
在《Racket参考》的“(lambda)”中提供了更多函数表达式的内容。
case-lambda表创建一个函数,它可以根据提供的参数数量而具有完全不同的行为。一个case-lambda表达式有这样的表:
(case-lambda [formals body ...+] ...)
formals = (arg-id ...) | rest-id | (arg-id ...+ . rest-id)
每个[formals body ...+]类似于(lambda formals body ...+)。应用以case-lambda生成一个函数类似于应用一个lambda给匹配给定参数数量的第一种情况。
Examples:
(define greet (case-lambda [(name) (string-append "Hello, " name)] [(given surname) (string-append "Hello, " given " " surname)])) > (greet "John") "Hello, John"
> (greet "John" "Smith") "Hello, John Smith"
> (greet) greet: arity mismatch;
the expected number of arguments does not match the given
number
given: 0
一个case-lambda函数不能直接支持可选参数或关键字参数。