7.8

#### 7.1mischief/function: Higher Order Functions

 (require mischief/function) package: mischief

 procedure(arg+ proc arg ...) → procedure? proc : procedure? arg : any/c
 procedure(arg+-right proc arg ...) → procedure? proc : procedure? arg : any/c
Partially applies proc to the given args, which may include keyword arguments. The args are added as either the leftmost or rightmost arguments to proc, respectively.

Examples:
 > (define one-two (arg+ list 1 2)) > (one-two 3 4) '(1 2 3 4) > (define sort< (arg+-right sort < #:cache-keys? #true)) > (sort< '("aunt" "anteater" "and" "an" "ant") #:key string-length) '("an" "and" "ant" "aunt" "anteater")

 procedure(call proc arg-or-keyword-arg ...) → any proc : procedure? arg-or-keyword-arg : any/c
Applies proc to the given arg-or-keyword-args. Equivalent to (proc arg-or-keyword-arg ...).

Examples:
 > (map call (list add1 sub1 - /) (list 1 2 3 4)) '(2 1 -3 1/4) > (call sort '(one two three) stringstring) '(one three two)

 procedure(keyword-call proc ks vs x ...) → any proc : procedure? ks : (listof keyword?) vs : list? x : any/c
Applies proc to the positional arguments x ... and keyword arguments ks with values vs. Equivalent to (keyword-apply proc ks vs (list x ...)).

Example:
 > (keyword-call sort '(#:cache-keys? key) (list #false first) '([2 a] [1 b] [3 c]) <)

keyword-apply: contract violation

expected: (listof keyword?)

given: '(#:cache-keys? key)

argument position: 2nd

other arguments...:

#<procedure:sort>

'(#f #<procedure:first>)

'(((2 a) (1 b) (3 c)) #<procedure:<>)

 procedure(conjoin proc ...) → procedure? proc : procedure?
 procedure(disjoin proc ...) → procedure? proc : procedure?
Produce the conjunction or disjunction, respectively, of the given predicates.

Examples:
 > (define positive-integer? (conjoin positive? integer?)) > (positive-integer? 1) #t > (positive-integer? -1) #f > (positive-integer? 1.5) #f > (define <=? (disjoin < =)) > (<=? 1 2) #t > (<=? 1 1) #t > (<=? 2 1) #f > (define always-true (disjoin (const #true) error)) > (always-true #:irrelevant 'keyword) #t > (define never-true (conjoin (const #false) error)) > (never-true #:irrelevant 'keyword) #f

 procedure(dynamic-wrap-procedure proc wrap) → procedure? proc : procedure? wrap : (-> (-> any) any)
Creates a procedure that invokes proc with its given arguments, but in a dynamic context established by wrap, such as the dynamic extent of parameterize.

Examples:
 > (define (silent proc) (dynamic-wrap-procedure proc (lambda {thunk} (parameterize {[current-output-port (open-output-nowhere)]} (thunk)))))
> (define silent-write (silent write))
> (silent-write '(1 2 3))
> (silent-write '(1 2 3) (current-output-port))

(1 2 3)

 > (with-output-to-string (lambda {} (silent-write "good night moon")))

""

 procedure arity : procedure-arity?
Produces a canonical form for the representation of a procedure’s arity.

Example:
 > (normalize-procedure-arity (list 1 (arity-at-least 3) 0 4)) (list 0 1 (arity-at-least 3))

 syntax(eta proc-expr)
Eta-expands proc-expr; in other words, produces a procedure that behaves identically to proc-expr, except that proc-expr is not evaluated until the first time it is called.

Strictly speaking, eta-expansion would evaluate proc-expr every time it is called; the eta macro memoizes proc-expr itself. It does not memoize the results of the procedure proc-expr returns.

Examples:
 > (define is-a-list? (disjoin empty? (conjoin cons? (compose (eta is-a-list?) rest))))
> (is-a-list? '(1 2 3))

#t

> (is-a-list? '(1 2 3 . more))

rest: contract violation

expected: (and/c list? (not/c empty?))

given: '(1 2 3 . more)

 syntax(define/keywords (name-id keys-id vals-id . formals) body ...+)
 syntax(lambda/keywords {keys-id vals-id . formals} body ...+)
Define or construct, respectively, a procedure that accepts arbitrary keyword arguments, binding the list of keywords to keys-id and their respective values to vals-id.

Examples:
 > (define/keywords (f keys vals . others) (list keys vals others))
> (f #:x 1 2 3 #:y 4)

'((#:x #:y) (1 4) (2 3))