Supporting multi-in

:: Racket, Emacs

In racket-mode I improved support for the multi-in form provided by racket/require.

What is multi-in?

Instead of:

1
2
3
4
5
(require net/uri-codec
         net/url
         racket/contract
         racket/format
         racket/string)

You can say:

1
2
3
(require racket/require
         (multi-in net (uri-codec url))
         (multi-in racket (contract format string)))

One detail: The racket/require must appear before any multi-in forms. Any sorting must make an exception for this.

What are the racket-{tidy trim base}-requires commands?

What are the changes?

  1. Sorting makes sure to keep racket/require first.

  2. If racket/require is present in the original require form(s), then multi-in is used when tidying.

  3. Any analysis that says requires should be removed, should handle multi-in forms.

Essentially, the commands first “expand” or “explode” multi-in forms to individual requires, do any analysis and modifications, then try to “unexpand” or “implode” them back again.1

All together, these changes close issues 355, 356, and 369.

Example without racket/require

Here’s an example where racket/require is not in the original require forms:

1
2
3
4
5
6
7
#lang racket

(require net/url)
(require net/uri-codec)

;; Just some expressions using imported definitions
string-join ~a get-pure-port uri-decode (match-define (list n) (list 1))

After M-x racket-base-requires:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#lang racket/base

(require net/uri-codec
         net/url
         racket/format
         racket/match
         racket/string)

;; Just some expressions using imported definitions
string-join ~a get-pure-port uri-decode (match-define (list n) (list 1))

Example with racket/require

Here’s an example where racket/require is in the original require forms:

1
2
3
4
5
6
7
8
#lang racket

(require racket/require) ;new
(require net/url)
(require net/uri-codec)

;; Just some expressions using imported definitions
string-join ~a get-pure-port uri-decode (match-define (list n) (list 1))

After M-x racket-base-requires:

1
2
3
4
5
6
7
8
#lang racket/base

(require racket/require
         (multi-in net (uri-codec url))
         (multi-in racket (format match string)))

;; Just some expressions using imported definitions
string-join ~a get-pure-port uri-decode (match-define (list n) (list 1))
  1. Not everything survives a round-trip, exactly. A Cartesian product like (multi-in (a b) (c d)) will end up as a (multi-in a (c d)) and a (multi-in b (c d)) — equivalent but not as concise.