/collects/scribblings/guide/lambda.scrbl

http://github.com/gmarceau/PLT · Racket · 244 lines · 192 code · 52 blank · 0 comment · 3 complexity · 4018bf70157ad8b3c0e625f21f239670 MD5 · raw file

  1. #lang scribble/doc
  2. @(require scribble/manual scribble/eval "guide-utils.rkt")
  3. @(define greet-eval (make-base-eval))
  4. @title[#:tag "lambda"]{Functions@aux-elem{ (Procedures)}: @racket[lambda]}
  5. A @racket[lambda] expression creates a function. In the simplest
  6. case, a @racket[lambda] expression has the form
  7. @specform[
  8. (lambda (arg-id ...)
  9. body ...+)
  10. ]
  11. A @racket[lambda] form with @math{n} @racket[_arg-id]s accepts
  12. @math{n} arguments:
  13. @interaction[
  14. ((lambda (x) x)
  15. 1)
  16. ((lambda (x y) (+ x y))
  17. 1 2)
  18. ((lambda (x y) (+ x y))
  19. 1)
  20. ]
  21. @;------------------------------------------------------------------------
  22. @section[#:tag "rest-args"]{Declaring a Rest Argument}
  23. A @racket[lambda] expression can also have the form
  24. @specform[
  25. (lambda rest-id
  26. body ...+)
  27. ]
  28. That is, a @racket[lambda] expression can have a single
  29. @racket[_rest-id] that is not surrounded by parentheses. The resulting
  30. function accepts any number of arguments, and the arguments are put
  31. into a list bound to @racket[_rest-id].
  32. @examples[
  33. ((lambda x x)
  34. 1 2 3)
  35. ((lambda x x))
  36. ((lambda x (car x))
  37. 1 2 3)
  38. ]
  39. Functions with a @racket[_rest-id] often use @racket[apply] to call
  40. another function that accepts any number of arguments.
  41. @guideother{@secref["apply"] describes @racket[apply].}
  42. @defexamples[
  43. (define max-mag
  44. (lambda nums
  45. (apply max (map magnitude nums))))
  46. (max 1 -2 0)
  47. (max-mag 1 -2 0)
  48. ]
  49. The @racket[lambda] form also supports required arguments combined
  50. with a @racket[_rest-id]:
  51. @specform[
  52. (lambda (arg-id ...+ . rest-id)
  53. body ...+)
  54. ]
  55. The result of this form is a function that requires at least as many
  56. arguments as @racket[_arg-id]s, and also accepts any number of
  57. additional arguments.
  58. @defexamples[
  59. (define max-mag
  60. (lambda (num . nums)
  61. (apply max (map magnitude (cons num nums)))))
  62. (max-mag 1 -2 0)
  63. (max-mag)
  64. ]
  65. A @racket[_rest-id] variable is sometimes called a @defterm{rest
  66. argument}, because it accepts the ``rest'' of the function arguments.
  67. @;------------------------------------------------------------------------
  68. @section{Declaring Optional Arguments}
  69. Instead of just an identifier, an argument (other than a rest
  70. argument) in a @racket[lambda] form can be specified with an
  71. identifier and a default value:
  72. @specform/subs[
  73. (lambda gen-formals
  74. body ...+)
  75. ([gen-formals (arg ...)
  76. rest-id
  77. (arg ...+ . rest-id)]
  78. [arg arg-id
  79. [arg-id default-expr]])
  80. ]{}
  81. An argument of the form @racket[[arg-id default-expr]] is
  82. optional. When the argument is not supplied in an application,
  83. @racket[_default-expr] produces the default value. The
  84. @racket[_default-expr] can refer to any preceding @racket[_arg-id],
  85. and every following @racket[_arg-id] must have a default as well.
  86. @defexamples[
  87. (define greet
  88. (lambda (given [surname "Smith"])
  89. (string-append "Hello, " given " " surname)))
  90. (greet "John")
  91. (greet "John" "Doe")
  92. ]
  93. @def+int[
  94. (define greet
  95. (lambda (given [surname (if (equal? given "John")
  96. "Doe"
  97. "Smith")])
  98. (string-append "Hello, " given " " surname)))
  99. (greet "John")
  100. (greet "Adam")
  101. ]
  102. @section[#:tag "lambda-keywords"]{Declaring Keyword Arguments}
  103. A @racket[lambda] form can declare an argument to be passed by
  104. keyword, instead of position. Keyword arguments can be mixed with
  105. by-position arguments, and default-value expressions can be supplied
  106. for either kind of argument:
  107. @guideother{@secref["keyword-args"] introduces function
  108. calls with keywords.}
  109. @specform/subs[
  110. (lambda gen-formals
  111. body ...+)
  112. ([gen-formals (arg ...)
  113. rest-id
  114. (arg ...+ . rest-id)]
  115. [arg arg-id
  116. [arg-id default-expr]
  117. (code:line arg-keyword arg-id)
  118. (code:line arg-keyword [arg-id default-expr])])
  119. ]{}
  120. An argument specified as @racket[(code:line _arg-keyword _arg-id)] is
  121. supplied by an application using the same @racket[_arg-keyword]. The
  122. position of the keyword--identifier pair in the argument list does not
  123. matter for matching with arguments in an application, because it will
  124. be matched to an argument value by keyword instead of by position.
  125. @def+int[
  126. (define greet
  127. (lambda (given #:last surname)
  128. (string-append "Hello, " given " " surname)))
  129. (greet "John" #:last "Smith")
  130. (greet #:last "Doe" "John")
  131. ]
  132. An @racket[(code:line _arg-keyword [_arg-id _default-expr])] argument
  133. specifies a keyword-based argument with a default value.
  134. @defexamples[
  135. #:eval greet-eval
  136. (define greet
  137. (lambda (#:hi [hi "Hello"] given #:last [surname "Smith"])
  138. (string-append hi ", " given " " surname)))
  139. (greet "John")
  140. (greet "Karl" #:last "Marx")
  141. (greet "John" #:hi "Howdy")
  142. (greet "Karl" #:last "Marx" #:hi "Guten Tag")
  143. ]
  144. The @racket[lambda] form does not directly support the creation
  145. of a function that accepts ``rest'' keywords. To construct a
  146. function that accepts all keyword arguments, use
  147. @racket[make-keyword-procedure]. The function supplied to
  148. @racket[make-keyword-procedure] receives keyword arguments
  149. through parallel lists in the first two (by-position) arguments,
  150. and then all by-position arguments from an application as the
  151. remaining by-position arguments.
  152. @guideother{@secref["apply"] introduces @racket[keyword-apply].}
  153. @defexamples[
  154. #:eval greet-eval
  155. (define (trace-wrap f)
  156. (make-keyword-procedure
  157. (lambda (kws kw-args . rest)
  158. (printf "Called with ~s ~s ~s\n" kws kw-args rest)
  159. (keyword-apply f kws kw-args rest))))
  160. ((trace-wrap greet) "John" #:hi "Howdy")
  161. ]
  162. @refdetails["lambda"]{function expressions}
  163. @;------------------------------------------------------------------------
  164. @section[#:tag "case-lambda"]{Arity-Sensitive Functions: @racket[case-lambda]}
  165. The @racket[case-lambda] form creates a function that can have
  166. completely different behaviors depending on the number of arguments
  167. that are supplied. A case-lambda expression has the form
  168. @specform/subs[
  169. (case-lambda
  170. [formals body ...+]
  171. ...)
  172. ([formals (arg-id ...)
  173. rest-id
  174. (arg-id ...+ . rest-id)])
  175. ]
  176. where each @racket[[_formals _body ...+]] is analogous to @racket[(lambda
  177. _formals _body ...+)]. Applying a function produced by
  178. @racket[case-lambda] is like applying a @racket[lambda] for the first
  179. case that matches the number of given arguments.
  180. @defexamples[
  181. (define greet
  182. (case-lambda
  183. [(name) (string-append "Hello, " name)]
  184. [(given surname) (string-append "Hello, " given " " surname)]))
  185. (greet "John")
  186. (greet "John" "Smith")
  187. (greet)
  188. ]
  189. A @racket[case-lambda] function cannot directly support optional or
  190. keyword arguments.
  191. @; ----------------------------------------------------------------------
  192. @close-eval[greet-eval]