17.1 Module Languages
Link to this section with
@secref["module-languages" #:doc '(lib "scribblings/guide/guide.scrbl")]
Link to this section with
@secref["module-languages" #:doc '(lib "scribblings/guide/guide.scrbl")]
When using the longhand 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 require, the initial import can be
called a module language.
The most common module languages are racket or
racket/base, but you can define your own
module language by defining a suitable module. For example,
using provide subforms like all-from-out,
except-out, and rename-out, you can add, remove, or
rename bindings from racket to produce a module
language that is a variant of racket:
The module Form introduces the longhand
module form.
|
|
> (module score 'raquet | (map (function (points) (case points | [(0) "love"] [(1) "fifteen"] | [(2) "thirty"] [(3) "forty"])) | (list 0 2))) |
|
|
> (require 'score) |
'("love" "thirty") |
|
17.1.1 Implicit Form Bindings
Link to this section with
@secref["implicit-forms" #:doc '(lib "scribblings/guide/guide.scrbl")]
Link to this section with
@secref["implicit-forms" #:doc '(lib "scribblings/guide/guide.scrbl")]
If you try to remove too much from racket in defining
your own module language, then the resulting module
will no longer work right as a module language:
|
|
|
eval:2:0: module: no #%module-begin binding in the module's |
language |
in: (module identity (quote just-lambda) (lambda (x) x)) |
The #%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 module language:
The other implicit forms provided by racket/base are
#%app for function calls, #%datum for literals, and
#%top for identifiers that have no binding:
Implicit forms such as #%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 lambda-calculus
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:
|
|
|
|
> (require 'ok) |
'z |
|
|
eval:4:0: lambda: use does not match pattern: (lambda (x) |
expr) |
in: (lambda (x y) x) |
|
eval:5:0: #%module-begin: use does not match pattern: |
(#%module-begin e) |
in: (#%module-begin (lambda (x) x) (lambda (y) (y y))) |
|
eval:6:0: #%app: use does not match pattern: (#%app e1 e2) |
in: (#%app x x x) |
> (module not-ok 'lambda-calculus | 10) |
|
eval:7:0: #%datum: no |
in: (#%datum . 10) |
Module languages rarely redefine #%app, #%datum, and
#%top, but redefining #%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 page, an alternate #%module-begin
can help eliminate provide and quasiquoting
boilerplate, as in "html.rkt":
"html.rkt"
Using the "html.rkt" module language, a simple web page
can be described without having to explicitly define or export
page and starting in quasiquoted mode instead
of expression mode:
> (module lady-with-the-spinning-head "html.rkt" | (title "Queen of Diamonds") | (p "Updated: " ,(now))) |
|
|
> (require 'lady-with-the-spinning-head) |
|
> page |
'(html (title "Queen of Diamonds") (p "Updated: " "2016-01-24")) |
Link to this section with
@secref["s-exp" #:doc '(lib "scribblings/guide/guide.scrbl")]
Link to this section with
@secref["s-exp" #:doc '(lib "scribblings/guide/guide.scrbl")]
Implementing a language at the level of #lang is more complex
than declaring a single module, because #lang lets programmers
control several different facets of a language. The
s-exp language, however, acts as a kind of
meta-language for using a module language with the
#lang shorthand:
is the same as
where name is derived from the source file containing the
#lang program. The name s-exp is short for
“S-expression,” which is a traditional name for
Racket’s reader-level lexical conventions: parentheses,
identifiers, numbers, double-quoted strings with certain backslash
escapes, and so on.
Using #lang s-exp, the
lady-with-the-spinning-head example from before can be
written more compactly as:
#lang s-exp "html.rkt" |
|
(title "Queen of Diamonds") |
(p "Updated: " ,(now)) |
Later in this guide, Defining new #lang Languages explains how to define
your own #lang language, but first we explain how you can write
reader-level extensions to Racket.