#lang scribble/doc @(require scribble/manual scribble/eval "guide-utils.rkt" "modfile.rkt" (for-label racket/date)) @title[#:tag "module-languages"]{Module Languages} When using the longhand @racket[module] form for writing modules, the module path that is specified after the new module's name provides the initial imports for the module. Since the initial-import module determines even the most basic bindings that are available in a module's body, such as @racket[require], the initial import can be called a @deftech{module language}. The most common @tech{module languages} are @racketmodname[racket] or @racketmodname[racket/base], but you can define your own @tech{module language} by defining a suitable module. For example, using @racket[provide] subforms like @racket[all-from-out], @racket[except-out], and @racket[rename-out], you can add, remove, or rename bindings from @racketmodname[racket] to produce a @tech{module language} that is a variant of @racketmodname[racket]: @guideother{@secref["module-syntax"] introduces the longhand @racket[module] form.} @interaction[ (module raquet racket (provide (except-out (all-from-out racket) lambda) (rename-out [lambda function]))) (module score 'raquet (map (function (points) (case points [(0) "love"] [(1) "fifteen"] [(2) "thirty"] [(3) "forty"])) (list 0 2))) (require 'score) ] @; ---------------------------------------- @section[#:tag "implicit-forms"]{Implicit Form Bindings} If you try to remove too much from @racketmodname[racket] in defining your own @tech{module language}, then the resulting module will no longer work right as a @tech{module language}: @interaction[ (module just-lambda racket (provide lambda)) (module identity 'just-lambda (lambda (x) x)) ] The @racket[#%module-begin] form is an implicit form that wraps the body of a module. It must be provided by a module that is to be used as @tech{module language}: @interaction[ (module just-lambda racket (provide lambda #%module-begin)) (module identity 'just-lambda (lambda (x) x)) (require 'identity) ] The other implicit forms provided by @racket[racket/base] are @racket[#%app] for function calls, @racket[#%datum] for literals, and @racket[#%top] for identifiers that have no binding: @interaction[ (module just-lambda racket (provide lambda #%module-begin (code:comment @#,t{@racketidfont{ten} needs these, too:}) #%app #%datum)) (module ten 'just-lambda ((lambda (x) x) 10)) (require 'ten) ] Implicit forms such as @racket[#%app] can be used explicitly in a module, but they exist mainly to allow a module language to restrict or change the meaning of implicit uses. For example, a @racket[lambda-calculus] @tech{module language} might restrict functions to a single argument, restrict function calls to supply a single argument, restrict the module body to a single expression, disallow literals, and treat unbound identifiers as uninterpreted symbols: @interaction[ (module lambda-calculus racket (provide (rename-out [1-arg-lambda lambda] [1-arg-app #%app] [1-form-module-begin #%module-begin] [no-literals #%datum] [unbound-as-quoted #%top])) (define-syntax-rule (1-arg-lambda (x) expr) (lambda (x) expr)) (define-syntax-rule (1-arg-app e1 e2) (#%app e1 e2)) (define-syntax-rule (1-form-module-begin e) (#%module-begin e)) (define-syntax (no-literals stx) (raise-syntax-error #f "no" stx)) (define-syntax-rule (unbound-as-quoted . id) 'id)) (module ok 'lambda-calculus ((lambda (x) (x z)) (lambda (y) y))) (require 'ok) (module not-ok 'lambda-calculus (lambda (x y) x)) (module not-ok 'lambda-calculus (lambda (x) x) (lambda (y) (y y))) (module not-ok 'lambda-calculus (lambda (x) (x x x))) (module not-ok 'lambda-calculus 10) ] Module languages rarely redefine @racket[#%app], @racket[#%datum], and @racket[#%top], but redefining @racket[#%module-begin] is more frequently useful. For example, when using modules to construct descriptions of HTML pages where a description is exported from the module as @racketidfont{page}, an alternate @racket[#%module-begin] can help eliminate @racket[provide] and quasiquoting boilerplate, as in @filepath{html.rkt}: @racketmodfile["html.rkt"] Using the @filepath{html.rkt} @tech{module language}, a simple web page can be described without having to explicitly define or export @racketidfont{page} and starting in @racket[quasiquote]d mode instead of expression mode: @interaction[ (module lady-with-the-spinning-head "html.rkt" (title "Queen of Diamonds") (p "Updated: " ,(now))) (require 'lady-with-the-spinning-head) page ] @; ---------------------------------------- @section[#:tag "s-exp"]{Using @racket[@#,hash-lang[] @#,racketmodname[s-exp]]} Implementing a language at the level of @hash-lang[] is more complex than declaring a single module, because @hash-lang[] lets programmers control several different facets of a language. The @racketmodname[s-exp] language, however, acts as a kind of meta-language for using a @tech{module language} with the @hash-lang[] shorthand: @racketmod[ s-exp _module-name _form ...] is the same as @racketblock[ (module _name _module-name _form ...) ] where @racket[_name] is derived from the source file containing the @hash-lang[] program. The name @racketmodname[s-exp] is short for ``@as-index{S-expression},'' which is a traditional name for Racket's @tech{reader}-level lexical conventions: parentheses, identifiers, numbers, double-quoted strings with certain backslash escapes, and so on. Using @racket[@#,hash-lang[] @#,racketmodname[s-exp]], the @racket[lady-with-the-spinning-head] example from before can be written more compactly as: @racketmod[ s-exp "html.rkt" (title "Queen of Diamonds") (p "Updated: " ,(now)) ] Later in this guide, @secref["hash-languages"] explains how to define your own @hash-lang[] language, but first we explain how you can write @tech{reader}-level extensions to Racket.