7.1 mischief/function: Higher Order Functions
(require mischief/function) | package: mischief-dev |
procedure
(arg+ proc arg ...) → procedure?
proc : procedure? arg : any/c
procedure
(arg+-right proc arg ...) → procedure?
proc : procedure? arg : any/c
> (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
proc : procedure? arg-or-keyword-arg : any/c
> (map call (list add1 sub1 - /) (list 1 2 3 4)) '(2 1 -3 1/4)
> (call sort '(one two three) string<? #:key symbol->string) '(one three two)
procedure
(keyword-call proc ks vs x ...) → any
proc : procedure? ks : (listof keyword?) vs : list? x : any/c
> (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?
> (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)
> (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
(normalize-procedure-arity arity) → procedure-arity?
arity : procedure-arity?
> (normalize-procedure-arity (list 1 (arity-at-least 3) 0 4)) (list 0 1 (arity-at-least 3))
syntax
(eta proc-expr)
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.
> (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/keywords (f keys vals . others) (list keys vals others)) > (f #:x 1 2 3 #:y 4) '((#:x #:y) (1 4) (2 3))