3.8 Procedure Expressions: lambda and case-lambda
Functions: lambda in The Racket Guide introduces procedure expressions.
(lambda kw-formals body ...+)
(λ kw-formals body ...+)
kw-formals = (arg ...) | (arg ...+ . rest-id) | rest-id arg = id | [id default-expr] | keyword id | keyword [id default-expr]
Considering only the first arg case, a simple kw-formals has one of the following three forms:
The procedure accepts as many non-keyword argument values as the number of ids. Each id is associated with an argument value by position.
(id ...+ . rest-id)
The procedure accepts any number of non-keyword arguments greater or equal to the number of ids. When the procedure is applied, the ids are associated with argument values by position, and all leftover arguments are placed into a list that is associated to rest-id.
The procedure accepts any number of non-keyword arguments. All arguments are placed into a list that is associated with rest-id.
More generally, an arg can include a keyword and/or default value. Thus, the first two cases above are more completely specified as follows:
Each arg has the following four forms:
Adds one to both the minimum and maximum number of non-keyword arguments accepted by the procedure. The id is associated with an actual argument by position.
Adds one to the maximum number of non-keyword arguments accepted by the procedure. The id is associated with an actual argument by position, and if no such argument is provided, the default-expr is evaluated to produce a value associated with id. No arg with a default-expr can appear before an id without a default-expr and without a keyword.
The procedure requires a keyword-based argument using keyword. The id is associated with a keyword-based actual argument using keyword.
keyword [id default-expr]
The procedure accepts a keyword-based argument using keyword. The id is associated with a keyword-based actual argument using keyword, if supplied in an application; otherwise, the default-expr is evaluated to obtain a value to associate with id.
The position of a keyword arg in kw-formals does not matter, but each specified keyword must be distinct.
(arg ...+ . rest-id)
Like the previous case, but the procedure accepts any number of non-keyword arguments beyond its minimum number of arguments. When more arguments are provided than non-keyword arguments among the args, the extra arguments are placed into a list that is associated to rest-id.
In other words, argument bindings with default-value expressions are evaluated analogous to let*.
If any identifier appears in the bodys that is not one of the identifiers in kw-formals, then it refers to the same location that it would if it appeared in place of the lambda expression. (In other words, variable reference is lexically scoped.)
When multiple identifiers appear in a kw-formals, they must be distinct according to bound-identifier=?.
If the procedure produced by lambda is applied to fewer or more by-position or by-keyword arguments than it accepts, to by-keyword arguments that it does not accept, or without required by-keyword arguments, then the exn:fail:contract exception is raised.
The last body expression is in tail position with respect to the procedure body.
> ((lambda (x) x) 10)
> ((lambda (x y) (list y x)) 1 2)
> ((lambda (x [y 5]) (list y x)) 1 2)
> (let ([f (lambda (x #:arg y) (list y x))]) (list (f 1 #:arg 2) (f #:arg 2 1)))
'((2 1) (2 1))
When compiling a lambda or case-lambda expression, Racket looks for a 'method-arity-error property attached to the expression (see Syntax Object Properties). If it is present with a true value, and if no case of the procedure accepts zero arguments, then the procedure is marked so that an exn:fail:contract:arity exception involving the procedure will hide the first argument, if one was provided. (Hiding the first argument is useful when the procedure implements a method, where the first argument is implicit in the original source). The property affects only the format of exn:fail:contract:arity exceptions, not the result of procedure-arity.
When a keyword-accepting procedure is bound to an identifier in
certain ways, and when the identifier is used in the function position
of an application form, then the application form may be expanded in
such a way that the original binding is obscured as the target of the
application. To help expose the connection between the function
application and function declaration, an identifier in the expansion
of the function application is tagged with a syntax property
accessible via syntax-procedure-alias-property if it is effectively an alias
for the original identifier. An identifier in the expansion is tagged with a
syntax property accessible via syntax-procedure-converted-arguments-property if it
is like the original identifier except that the arguments are converted to a
flattened form: keyword arguments, required by-position arguments,
by-position optional arguments, and rest arguments—
(case-lambda [formals body ...+] ...)
formals = (id ...) | (id ...+ . rest-id) | rest-id
Note that a case-lambda clause supports only formals, not the more general kw-formals of lambda. That is, case-lambda does not directly support keyword and optional arguments.
> (let ([f (case-lambda [() 10] [(x) x] [(x y) (list y x)] [r r])]) (list (f) (f 1) (f 1 2) (f 1 2 3)))
'(10 1 (2 1) (1 2 3))
(#%plain-lambda formals body ...+)