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

6.7 KiB

Function Calls Procedure Applications

An expression of the form

(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-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:

> (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.

(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")

+[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:

(define (avg lst) ; doesnt work...
  (/ (+ lst) (length lst)))        
> (avg '(1 2 3))                   
+: contract violation              
  expected: number?                
  given: '(1 2 3)                  
(define (avg lst) ; doesnt 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 applys 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"))