160 lines
4.2 KiB
Racket
160 lines
4.2 KiB
Racket
#reader(lib "docreader.ss" "scribble")
|
|
@require[(lib "manual.ss" "scribble")]
|
|
@require[(lib "eval.ss" "scribble")]
|
|
@require["guide-utils.ss"]
|
|
|
|
@title[#:tag "guide:lambda"]{Procedures}
|
|
|
|
A @scheme[lambda] expression creates a procedure. In the simplest
|
|
case, a @scheme[lambda] expression has the form
|
|
|
|
@specform[
|
|
(lambda (arg-id ...)
|
|
body-expr ...+)
|
|
]
|
|
|
|
The @scheme[...+] in this syntactic sketch means ``one or more
|
|
repetitions of the preceeding element;'' that is, one or more
|
|
@scheme[_body-expr]s.
|
|
|
|
A @scheme[lambda] form with @math{n} @scheme[_arg-id]s accepts
|
|
@math{n} arguments:
|
|
|
|
@interaction[
|
|
((lambda (x) x)
|
|
1)
|
|
((lambda (x y) (+ x y))
|
|
1 2)
|
|
((lambda (x y) (+ x y))
|
|
1)
|
|
]
|
|
|
|
A @scheme[lambda] expression can also have the form
|
|
|
|
@specform[
|
|
(lambda rest-id
|
|
body-expr ...+)
|
|
]
|
|
|
|
That is, a @scheme[lambda] expression can have a single
|
|
@scheme[_rest-id] that is not surrounded by parentheses. The resulting
|
|
procedure accepts any number of arguments, and the arguments are put
|
|
into a list bound to @scheme[_rest-id].
|
|
|
|
@examples[
|
|
((lambda x x)
|
|
1 2 3)
|
|
((lambda x x))
|
|
((lambda x (car x))
|
|
1 2 3)
|
|
]
|
|
|
|
Combining thes two styles, a @scheme[lambda] expression can have the
|
|
form
|
|
|
|
@specform[
|
|
(lambda (arg-id ...+ . rest-id)
|
|
body-expr ...+)
|
|
]
|
|
|
|
The result is a procedure that requires at least as many arguments as
|
|
@scheme[_arg-id]s, and also accepts any number of additional
|
|
arguments.
|
|
|
|
@examples[
|
|
((lambda (a b . x) (cons (/ a b) x))
|
|
1 2 3 4)
|
|
((lambda (a b . x) (cons (/ a b) x))
|
|
1 2)
|
|
((lambda (a b . x) (cons (/ a b) x))
|
|
1)
|
|
]
|
|
|
|
Support for optional and keyword arguments lead to even more
|
|
possibilities:
|
|
|
|
@itemize{
|
|
|
|
@item{Instead of just an @scheme[_arg-id], an form argument can be
|
|
@scheme[[_arg-id _default-expr]], which means that the argument
|
|
is optional. When the argument is not supplied,
|
|
@scheme[_default-expr] produces the default value. The
|
|
@scheme[_default-expr] can refer to any preceding
|
|
@scheme[_arg-id], and every following @scheme[_arg-id] must
|
|
have a default as well.
|
|
|
|
@examples[
|
|
((lambda (x [y 5]) (list x y))
|
|
1 2)
|
|
((lambda (x [y 5]) (list x y))
|
|
1)
|
|
((lambda (x [y (+ x 1)]) (list x y))
|
|
1)
|
|
(lambda ([x 5] y) (list x y))
|
|
]}
|
|
|
|
@item{Instead of just an @scheme[_arg-id], an form argument can be
|
|
@scheme[(code:line _keyword _arg-id)], which indicates a
|
|
by-keyword argument instead of a by-position argument. The
|
|
position of the keyword--identifier pair in the argument list
|
|
does not matter for matching with arguments in an application,
|
|
because it will be matched to an argument value by keyword
|
|
insteda of by position.
|
|
|
|
@examples[
|
|
((lambda (x #:second y) (list x y))
|
|
1 #:second 2)
|
|
((lambda (x #:second y) (list x y))
|
|
#:second 2 1)
|
|
((lambda (#:second y x) (list x y))
|
|
1 #:second 2)
|
|
((lambda (x #:second y) (list x y))
|
|
1 2)
|
|
((lambda (x #:second y) (list x y))
|
|
#:second 2)
|
|
]}
|
|
|
|
@item{The previous two possibilities can be combined to specify a
|
|
by-keyword argument with a default value.
|
|
|
|
@examples[
|
|
((lambda (x #:second [y 5]) (list x y))
|
|
1 #:second 2)
|
|
((lambda (x #:second [y 5]) (list x y))
|
|
1)
|
|
]}
|
|
|
|
}
|
|
|
|
The @scheme[case-lambda] form creates a procedure that can have
|
|
completely different behaviors depending on the number of arguments
|
|
that are supplied. A case-lambda expression has the form
|
|
|
|
@specform[
|
|
(case-lambda
|
|
[formals body-expr ...+]
|
|
...)
|
|
]
|
|
|
|
where each @scheme[_formals _body-expr ...+] is anlogous to
|
|
@scheme[(lambda _formals _body-expr ...+)]. That is, a
|
|
@scheme[_formals] can be @scheme[(_arg-id ...)], @scheme[_rest-id], or
|
|
@scheme[(_arg-id ... . _rest-id)].
|
|
|
|
Applying a procedure produced by @scheme[case-lambda] is like applying
|
|
a @scheme[lambda] for the first case that matches the number of given
|
|
arguments.
|
|
|
|
@examples[
|
|
((case-lambda [() 10][(x y) (+ x y)])
|
|
1 2)
|
|
((case-lambda [() 10][(x y) (+ x y)]))
|
|
((case-lambda [() 10][(x y) (+ x y)])
|
|
1)
|
|
]
|
|
|
|
A @scheme[case-lambda] procedure cannot directly support optional or
|
|
keyword arguments.
|
|
|
|
@refdetails["mz:lambda"]{procedure expressions}
|