4.3 Function Calls (Procedure Applications)
An expression of the form
(proc-expr arg-expr ...)
is a function call—
4.3.1 Evaluation Order and Arity
A function call is evaluated by first evaluating the proc-expr and all arg-exprs in order (left to right). Then, if proc-expr produces a function that accepts as many arguments as supplied arg-exprs, the function is called. Otherwise, an exception is raised.
Examples: | |||||||||||||||||||||
|
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 function’s arity is the number of arguments that it accepts.
4.3.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:
Keywords introduces keywords.
(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 args determines the order in which arg-exprs 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")
Procedure Applications and #%app in The Racket Reference provides more on procedure applications.
4.3.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:
(define (avg lst) ; doesn’t work... (/ (+ lst) (length lst)))
> (avg '(1 2 3)) +: contract violation
expected: number?
given: '(1 2 3)
(define (avg lst) ; doesn’t always work... (/ (+ (list-ref lst 0) (list-ref lst 1) (list-ref lst 2)) (length lst)))
> (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:
(define (avg lst) (/ (apply + lst) (length lst)))
> (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 consed onto the argument list:
(define (anti-sum lst) (apply - 0 lst))
> (anti-sum '(1 2 3)) -6
The apply function accepts keyword arguments, too, and it passes them along to the called function:
(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.
(keyword-apply go '(#:mode) '(fast) '("super.rkt"))