You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
typesetting/quad/qtest/mds/apply.md

183 lines
6.7 KiB
Markdown

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# Function Calls \(Procedure Applications\)
An expression of the form
```racket
(proc-expr arg-expr ...)
```
is a function call—also known as a _procedure application_—when
`proc-expr` is not an identifier that is bound as a syntax transformer
\(such as `if` or `define`\).
## 1. Evaluation Order and Arity
A function call is evaluated by first evaluating the `proc-expr` and all
`arg-expr`s in order \(left to right\). Then, if `proc-expr` produces a
function that accepts as many arguments as supplied `arg-expr`s, the
function is called. Otherwise, an exception is raised.
Examples:
```racket
> (cons 1 null)
'(1)
> (+ 1 2 3)
6
> (cons 1 2 3)
cons: arity mismatch;
the expected number of arguments does not match the given
number
expected: 2
given: 3
arguments...:
1
2
3
> (1 2 3)
application: not a procedure;
expected a procedure that can be applied to arguments
given: 1
arguments...:
2
3
```
Some functions, such as `cons`, accept a fixed number of arguments. Some
functions, such as `+` or `list`, accept any number of arguments. Some
functions accept a range of argument counts; for example `substring`
accepts either two or three arguments. A functions _arity_ is the
number of arguments that it accepts.
## 2. Keyword Arguments
Some functions accept _keyword arguments_ in addition to by-position
arguments. For that case, an `arg` can be an `arg-keyword arg-expr`
sequence instead of just a `arg-expr`:
> +\[missing\] introduces keywords.
```racket
(proc-expr arg ...)
arg = arg-expr
| arg-keyword arg-expr
```
For example,
`(go` `"super.rkt"` `#:mode` `'fast)`
calls the function bound to `go` with `"super.rkt"` as a by-position
argument, and with `'fast` as an argument associated with the `#:mode`
keyword. A keyword is implicitly paired with the expression that follows
it.
Since a keyword by itself is not an expression, then
`(go` `"super.rkt"` `#:mode` `#:fast)`
is a syntax error. The `#:mode` keyword must be followed by an
expression to produce an argument value, and `#:fast` is not an
expression.
The order of keyword `arg`s determines the order in which `arg-expr`s
are evaluated, but a function accepts keyword arguments independent of
their position in the argument list. The above call to `go` can be
equivalently written
`(go` `#:mode` `'fast` `"super.rkt")`
> +\[missing\] in \[missing\] provides more on procedure applications.
## 3. The `apply` Function
The syntax for function calls supports any number of arguments, but a
specific call always specifies a fixed number of arguments. As a result,
a function that takes a list of arguments cannot directly apply a
function like `+` to all of the items in a list:
```racket
(define (avg lst) ; doesnt work...
(/ (+ lst) (length lst)))
```
```racket
> (avg '(1 2 3))
+: contract violation
expected: number?
given: '(1 2 3)
```
```racket
(define (avg lst) ; doesnt always work...
(/ (+ (list-ref lst 0) (list-ref lst 1) (list-ref lst 2))
(length lst)))
```
```racket
> (avg '(1 2 3))
2
> (avg '(1 2))
list-ref: index too large for list
index: 2
in: '(1 2)
```
The `apply` function offers a way around this restriction. It takes a
function and a _list_ argument, and it applies the function to the
values in the list:
```racket
(define (avg lst)
(/ (apply + lst) (length lst)))
```
```racket
> (avg '(1 2 3))
2
> (avg '(1 2))
3/2
> (avg '(1 2 3 4))
5/2
```
As a convenience, the `apply` function accepts additional arguments
between the function and the list. The additional arguments are
effectively `cons`ed onto the argument list:
```racket
(define (anti-sum lst)
(apply - 0 lst))
```
```racket
> (anti-sum '(1 2 3))
-6
```
The `apply` function accepts keyword arguments, too, and it passes them
along to the called function:
```racket
(apply go #:mode 'fast '("super.rkt"))
(apply go '("super.rkt") #:mode 'fast)
```
Keywords that are included in `apply`s list argument do not count as
keyword arguments for the called function; instead, all arguments in
this list are treated as by-position arguments. To pass a list of
keyword arguments to a function, use the `keyword-apply` function, which
accepts a function to apply and three lists. The first two lists are in
parallel, where the first list contains keywords \(sorted by
`keyword<?`\), and the second list contains a corresponding argument for
each keyword. The third list contains by-position function arguments, as
for `apply`.
```racket
(keyword-apply go
'(#:mode)
'(fast)
'("super.rkt"))
```