From 1b729d34d8a4f7bca411f373c1372e7bef7981f4 Mon Sep 17 00:00:00 2001 From: Ryan Culpepper Date: Sun, 24 Mar 2013 18:05:41 -0400 Subject: [PATCH] added rename option to lazy-require closes PR 13624 also added examples --- collects/racket/lazy-require.rkt | 104 +++++++++++--------- collects/scribblings/reference/syntax.scrbl | 35 +++++-- 2 files changed, 87 insertions(+), 52 deletions(-) diff --git a/collects/racket/lazy-require.rkt b/collects/racket/lazy-require.rkt index 6c638aacb3..5530d0c170 100644 --- a/collects/racket/lazy-require.rkt +++ b/collects/racket/lazy-require.rkt @@ -37,59 +37,71 @@ (define-syntax (lazy-require1 stx) (syntax-case stx () - [(lazy-require1 modpath (name ...) orig-stx) - (with-syntax ([(defn ...) - (for/list ([name (in-list (syntax->list #'(name ...)))]) - (unless (identifier? name) - (raise-syntax-error #f "expected identifier" #'orig-stx name)) - (with-syntax ([name name] - [(aux) (generate-temporaries (list name))]) - #`(begin (define aux (make-lazy-function 'name get-sym)) - (define-syntax name - (make-rename-transformer - (syntax-property (quote-syntax aux) - 'not-provide-all-defined #t))))))] - [define-mpi-var - (let ([phase (sub1 (variable-reference->phase (#%variable-reference)))]) - (if (zero? phase) - ;; `define-runtime-module-path-index' works right at phase-level 0: - #'(define-runtime-module-path-index mpi-var (quote modpath)) - ;; need a submodule: - (with-syntax ([lazy-require-path-n - (string->symbol - (format "lazy-require-path-~a-~a" - phase - counter))] - ;; May need to adjust modpath, since we're interpreting it - ;; relative to a *submodule* of the original context. - ;; ie, module-path interpretation is not hygienic! - [modpath* (module-path-add-submod-up #'modpath)]) - (set! counter (add1 counter)) - #'(begin - (module lazy-require-path-n racket/base - (require racket/runtime-path - (for-syntax racket/base)) - (provide mpi-var) - (define-runtime-module-path-index mpi-var (quote modpath*))) - (require 'lazy-require-path-n)))))]) - #'(begin - define-mpi-var - (define (get-sym sym) - (parameterize ((current-namespace (variable-reference->namespace (#%variable-reference)))) - (begin0 - (dynamic-require mpi-var sym) - (do-registration (#%variable-reference) (quote modpath))))) - defn ...))])) + [(lazy-require1 modpath (thing ...) orig-stx) + (with-syntax ([((exp-name bind-name) ...) + (for/list ([thing-stx (in-list (syntax->list #'(thing ...)))]) + (syntax-case thing-stx () + [name + (identifier? #'name) + (list #'name #'name)] + [[exp-name bind-name] + (begin + (unless (identifier? #'exp-name) + (raise-syntax-error #f "expected identifier" + #'orig-stx #'exp-name)) + (unless (identifier? #'bind-name) + (raise-syntax-error #f "expected identifier" + #'orig-stx #'bind-name)) + (list #'exp-name #'bind-name))] + [_ + (raise-syntax-error #f "expected identifier or pair of identifiers" + #'orig-stx thing-stx)]))] + [mpi-var-defn + (let ([phase (sub1 (variable-reference->phase (#%variable-reference)))]) + (if (zero? phase) + ;; `define-runtime-module-path-index' works right at phase-level 0: + #'(define-runtime-module-path-index mpi-var (quote modpath)) + ;; need a submodule: + (with-syntax ([lazy-require-path-n + (string->symbol + (format "lazy-require-path-~a-~a" + phase + counter))] + ;; May need to adjust modpath, since we're interpreting it + ;; relative to a *submodule* of the original context. + ;; ie, module-path interpretation is not hygienic! + [modpath* (module-path-add-submod-up #'modpath)]) + (set! counter (add1 counter)) + #'(begin + (module lazy-require-path-n racket/base + (require racket/runtime-path + (for-syntax racket/base)) + (provide mpi-var) + (define-runtime-module-path-index mpi-var (quote modpath*))) + (require (submod "." lazy-require-path-n))))))]) + (with-syntax ([(aux-name ...) (generate-temporaries #'(bind-name ...))]) + #'(begin + mpi-var-defn + (define (get-sym sym) + (parameterize ((current-namespace (variable-reference->namespace (#%variable-reference)))) + (begin0 + (dynamic-require mpi-var sym) + (do-registration (#%variable-reference) (quote modpath))))) + (define aux-name (make-lazy-function 'exp-name 'bind-name get-sym)) ... + (define-syntax bind-name + (make-rename-transformer + (syntax-property (quote-syntax aux-name) + 'not-provide-all-defined #t))) ...)))])) -(define (make-lazy-function name get-sym) +(define (make-lazy-function exp-name bind-name get-sym) ;; Use 'delay/sync' because 'delay' promise is not reentrant. ;; FIXME: OTOH, 'delay/sync' promise is not kill-safe. - (let ([fun-p (delay/sync (get-sym name))]) + (let ([fun-p (delay/sync (get-sym exp-name))]) (procedure-rename (make-keyword-procedure (lambda (kws kwargs . args) (keyword-apply (force fun-p) kws kwargs args))) - name))) + bind-name))) (define (do-registration vr modpath) (let ([path (resolved-module-path-name diff --git a/collects/scribblings/reference/syntax.scrbl b/collects/scribblings/reference/syntax.scrbl index ab523e87bd..483f1f11a1 100644 --- a/collects/scribblings/reference/syntax.scrbl +++ b/collects/scribblings/reference/syntax.scrbl @@ -2824,12 +2824,19 @@ heuristics, and should only be used when other inlining attempts (such as @note-lib-only[racket/lazy-require] -@defform[(lazy-require [module-path (imported-fun-id ...)] ...)]{ +@(define lazy-require-eval (make-base-eval)) +@(lazy-require-eval '(require racket/lazy-require)) -Defines each @racket[imported-fun-id] as a function that, when called, -dynamically requires the export named @racket[imported-fun-id] from -the module specified by @racket[module-path] and calls it with the -same arguments. +@defform[(lazy-require [module-path (fun-import ...)] ...) + #:grammar + ([fun-import fun-id + (orig-fun-id fun-id)])]{ + +Defines each @racket[fun-id] as a function that, when called, +dynamically requires the export named @racket[orig-fun-id] from the +module specified by @racket[module-path] and calls it with the same +arguments. If @racket[orig-fun-id] is not given, it defaults to +@racket[fun-id]. If the enclosing relative phase level is not 0, then @racket[module-path] is also placed in a submodule (with a use of @@ -2841,4 +2848,20 @@ submodule). Introduced submodules have the names When the use of a lazily-required function triggers module loading, @racket[register-external-module] declares a potential compilation dependency (in case the function is used in the process of compiling a -module).} +module). + +@examples[#:eval lazy-require-eval +(lazy-require + [racket/list (partition)]) +(partition even? '(1 2 3 4 5)) +(module hello racket/base + (provide hello) + (printf "starting hello server\n") + (define (hello) (printf "hello!\n"))) +(lazy-require + ['hello ([hello greet])]) +(greet) +] +} + +@(close-eval lazy-require-eval)