add 'compose' to scheme/base; switch Help Desk to a mzscheme app

svn: r7979
This commit is contained in:
Matthew Flatt 2007-12-12 22:17:09 +00:00
parent a58893f4ba
commit bd7ced966e
7 changed files with 78 additions and 59 deletions

View File

@ -1,7 +1,7 @@
#lang scheme/base #lang scheme/base
(require "search.ss" (require "search.ss"
browser/external net/sendurl ; browser/external
setup/dirs setup/dirs
mzlib/cmdline) mzlib/cmdline)

View File

@ -12,5 +12,5 @@
("help" "servlets" "scheme" "misc") ("help" "servlets" "scheme" "misc")
|# |#
)) ))
(define mred-launcher-libraries '("help.ss")) (define mzscheme-launcher-libraries '("help.ss"))
(define mred-launcher-names '("Help Desk"))) (define mzscheme-launcher-names '("Help Desk")))

View File

@ -7,7 +7,7 @@
scribble/basic scribble/basic
scribble/manual scribble/manual
(prefix-in scheme: scribble/scheme) (prefix-in scheme: scribble/scheme)
browser/external net/sendurl ; browser/external
mzlib/contract) mzlib/contract)
(provide/contract (provide/contract
@ -84,8 +84,6 @@
(send-url (format "file://~a" (path->string file))) (send-url (format "file://~a" (path->string file)))
(void)))) (void))))
(define ((compose f g) x) (f (g x)))
;; has-match : (listof regexp) -> entry -> boolean ;; has-match : (listof regexp) -> entry -> boolean
(define ((has-match search-regexps) entry) (define ((has-match search-regexps) entry)
(ormap (λ (str) (ormap (λ (str)

View File

@ -5,7 +5,8 @@
(only scheme/base (only scheme/base
build-string build-string
build-list build-list
build-vector) build-vector
compose)
"kw.ss") "kw.ss")
(require-for-syntax (lib "kerncase.ss" "syntax") (require-for-syntax (lib "kerncase.ss" "syntax")
@ -53,29 +54,6 @@
(define identity (lambda (x) x)) (define identity (lambda (x) x))
(define compose
(case-lambda
[(f) (if (procedure? f) f (raise-type-error 'compose "procedure" f))]
[(f g)
(let ([f (compose f)]
[g (compose g)])
(if (eqv? 1 (procedure-arity f)) ; optimize: don't use call-w-values
(if (eqv? 1 (procedure-arity g)) ; optimize: single arity everywhere
(lambda (x) (f (g x)))
(lambda args (f (apply g args))))
(if (eqv? 1 (procedure-arity g)) ; optimize: single input
(lambda (a)
(call-with-values
(lambda () (g a))
f))
(lambda args
(call-with-values
(lambda () (apply g args))
f)))))]
[(f . more)
(let ([m (apply compose more)])
(compose f m))]))
(define (loop-until start done? next body) (define (loop-until start done? next body)
(let loop ([i start]) (let loop ([i start])
(unless (done? i) (unless (done? i)

View File

@ -21,7 +21,9 @@
build-vector build-vector
build-string build-string
build-list) build-list
compose)
;; used by sort-internal; note that a and b are reversed, to we invert `less?' ;; used by sort-internal; note that a and b are reversed, to we invert `less?'
;; test ;; test
@ -317,4 +319,31 @@
(if (= i n) (if (= i n)
(reverse a) (reverse a)
(loop (add1 i) (loop (add1 i)
(cons (fcn i) a))))))) (cons (fcn i) a))))))
(define compose
(case-lambda
[(f) (if (procedure? f)
f
(raise-type-error 'compose "procedure" f))]
[(f g)
(let ([f (compose f)]
[g (compose g)])
(if (eqv? 1 (procedure-arity f)) ; optimize: don't use call-w-values
(if (eqv? 1 (procedure-arity g)) ; optimize: single arity everywhere
(lambda (x) (f (g x)))
(lambda args (f (apply g args))))
(if (eqv? 1 (procedure-arity g)) ; optimize: single input
(lambda (a)
(call-with-values
(lambda () (g a))
f))
(lambda args
(call-with-values
(lambda () (apply g args))
f)))))]
[(f . more)
(if (procedure? f)
(let ([m (apply compose more)])
(compose f m))
(compose f))])))

View File

@ -24,6 +24,20 @@ is called in tail position with respect to the @scheme[apply] call.
(apply + '()) (apply + '())
]} ]}
@defproc[(compose [proc procedure?] ...) procedure?]{
Returns a procedure that composes the given functions, applying the
last @scheme[proc] first and the first @scheme[proc] last. The
composed functions can consume and produce any number of values, as
long as each function produces as many values as the preceding
function consumes.
@examples[
((compose - sqrt) 10)
((compose sqrt -) 10)
((compose list split-path) (bytes->path #"/a" 'unix))
]}
@; ---------------------------------------- @; ----------------------------------------
@section{Keywords and Arity} @section{Keywords and Arity}

View File

@ -11,15 +11,15 @@
;; a context is either ;; a context is either
;; frame ;; frame
;; (compose context frame) ;; (ccompose context frame)
;; a frame is either ;; a frame is either
;; w -> target-redex ;; w -> target-redex
;; (listof w) -> target-redex ;; (listof w) -> target-redex
;; compose: (w -> target-expr) (alpha -> target-redex) -> (alpha -> target-expr) ;; ccompose: (w -> target-expr) (alpha -> target-redex) -> (alpha -> target-expr)
;; compose a context with a frame ;; compose a context with a frame
(define (compose ctxt frame) (define (ccompose ctxt frame)
(if (eq? ctxt id) (if (eq? ctxt id)
frame frame
(lambda (val) (lambda (val)
@ -61,9 +61,9 @@
(#%plain-app apply values #,ref-to-save)))))))] (#%plain-app apply values #,ref-to-save)))))))]
[(set! v ve) [(set! v ve)
(anormal (anormal
(compose ctxt (ccompose ctxt
(lambda (val) (lambda (val)
(quasisyntax/loc stx (set! v #,val)))) (quasisyntax/loc stx (set! v #,val))))
#'ve)] #'ve)]
[(let-values () be) [(let-values () be)
(anormal ctxt (syntax/loc stx be))] (anormal ctxt (syntax/loc stx be))]
@ -103,12 +103,12 @@
(syntax/loc stx (case-lambda [formals (begin be ...)] ...)))] (syntax/loc stx (case-lambda [formals (begin be ...)] ...)))]
[(if te ce ae) [(if te ce ae)
(anormal (anormal
(compose ctxt (ccompose ctxt
(lambda (val) (lambda (val)
(quasisyntax/loc stx (quasisyntax/loc stx
(if #,val (if #,val
#,(anormal-term #'ce) #,(anormal-term #'ce)
#,(anormal-term #'ae))))) #,(anormal-term #'ae)))))
#'te)] #'te)]
[(quote datum) [(quote datum)
(ctxt stx)] (ctxt stx)]
@ -116,23 +116,23 @@
(ctxt stx)] (ctxt stx)]
[(with-continuation-mark ke me be) [(with-continuation-mark ke me be)
(anormal (anormal
(compose ctxt (ccompose ctxt
(lambda (kev) (lambda (kev)
(anormal (anormal
(lambda (mev) (lambda (mev)
(quasisyntax/loc stx (quasisyntax/loc stx
(with-continuation-mark #,kev #,mev (with-continuation-mark #,kev #,mev
#,(anormal-term #'be)))) #,(anormal-term #'be))))
#'me))) #'me)))
#'ke)] #'ke)]
[(#%plain-app fe e ...) [(#%plain-app fe e ...)
(anormal (anormal
(lambda (val0) (lambda (val0)
(anormal* (anormal*
(compose ctxt (ccompose ctxt
(lambda (rest-vals) (lambda (rest-vals)
(quasisyntax/loc stx (quasisyntax/loc stx
(#%plain-app #,val0 #,@rest-vals)))) (#%plain-app #,val0 #,@rest-vals))))
(syntax->list #'(e ...)))) (syntax->list #'(e ...))))
#'fe)] #'fe)]
[(#%top . v) [(#%top . v)
@ -149,9 +149,9 @@
(elim-letrec-term stx))] (elim-letrec-term stx))]
[(#%expression d) [(#%expression d)
(anormal (anormal
(compose ctxt (ccompose ctxt
(lambda (d) (lambda (d)
(quasisyntax/loc stx (#%expression #,d)))) (quasisyntax/loc stx (#%expression #,d))))
#'d)] #'d)]
[_ [_
(raise-syntax-error 'anormal "Dropped through:" stx)]))) (raise-syntax-error 'anormal "Dropped through:" stx)])))