posted by Leif Andersen and Ben Greenman
Tired of writing
(require (for-syntax syntax/parse)) at the top of your Racket programs? This post shows how to make a
#lang to customize your default programming environment.
Let’s build a language
#lang scratch that:
enables Scribble’s @-syntax.
We’ll follow a three-step recipe:
build an empty
load the libraries, and
change the reader.
At the end, we’ll see how to make
scratch your default language in DrRacket.
First we need to make a
scratch/ directory with
$ mkdir scratch; cd scratch $ touch info.rkt $ touch main.rkt
info.rkt file, write:
main.rkt file, write:
Now from inside the
scratch/ directory, install the package:
$ raco pkg install
You are now the proud parent of a new Racket package.
raco-pkg-new is a shortcut for starting a new package.
For more information on the
info.rktfile format, see the
Any program can now
(require scratch) to import all bindings provided by the
main.rkt file. Our next step is to reprovide bindings from other libraries in
Since we want to use
scratch as a language, we also need to specify how to read a
scratch program. The
syntax/module-reader language provides a shorthand for doing so.
Here is the updated
provide form declares the exports of the
scratch module. In other words, if another module contains the form
(require scratch) then that module will import bindings from
reader submodule is written in the
syntax/module-reader language. This submodule imports all bindings from its enclosing module (
scratch, or to be slightly more precise “the toplevel module in the file
scratch/main.rkt”) and defines a language that provides those bindings and uses the reader from
In short, this code does what we want.
Yes it does.
Annoyed that the
provideforms are so similar? There’s a library for that.
Changing the Reader
Next, we want to enable the @-expression reader. This involves rexporting the scribble
read-syntax functions in the
reader submodule in
#lang racket/base (require racket/list (for-syntax racket/base syntax/parse)) (provide (all-from-out racket/list racket/base) (for-syntax (all-from-out racket/base syntax/parse))) (module* reader syntax/module-reader scratch #:read s:read #:read-syntax s:read-syntax (require (prefix-in s: scribble/reader)))
To test that it works, let’s embed some C syntax in our Racket program:
At this point, running
$ raco setup --check-pkg-deps scratchwill report an undeclared dependency on
at-exp-lib. Make sure to add
depslist in your
info.rktfile, or run
$ raco setup --fix-pkg-deps scratch
prefix-inis not necessary; it just clarifies where
If you think inline C strings are interesting, you should definitely watch Jay McCarthy’s RacketCon 2016 talk on remix.
scratch the default language for new files in DrRacket:
Click “Language” in the menu bar.
Click “Choose Language” in the drop-down menu.
Click the radio button for “The Racket Language”, then click the “Show Details” button at the bottom of the window.
#lang scratchin the text box labeled “Automatic
Click “Ok”, and that’s the end. Enjoy.
You can and should engineer the
#lang line of your Racket programs to remove unnecessary boilerplate and/or enforce a project-specific development environment.
Feel free to pubish your custom language on the Racket package server. (Make sure to run
$ raco setup --check-pkg-deps scratchbeforehand.)
The title “Languages as Dotfiles” is a reference to Languages as Libraries