6 What’s the point of splicing-let?

I stared at racket/splicing for the longest time. What does it do? Why would I use it? Why is it in the Macros section of the reference?

Step one, cut a hole in the box de-mythologize it. For example, using splicing-let like this:

> (require racket/splicing)
> (splicing-let ([x 0])
    (define (get-x)
      x))
; get-x is visible out here:
> (get-x)

0

; but x is not:
> x

x: undefined;

 cannot reference an identifier before its definition

  in module: 'program

is equivalent to:

> (define get-y
    (let ([y 0])
      (lambda ()
        y)))
; get-y is visible out here:
> (get-y)

0

; but y is not:
> y

y: undefined;

 cannot reference an identifier before its definition

  in module: 'program

This is the classic Lisp/Scheme/Racket idiom sometimes called "let over lambda". A koan about closures and objects. A closure hides y, which can only be accessed via get-y.

So why would we care about the splicing forms? They can be more concise, especially when there are multiple body forms:

> (require racket/splicing)
> (splicing-let ([x 0])
    (define (inc)
      (set! x (+ x 1)))
    (define (dec)
      (set! x (- x 1)))
    (define (get)
      x))

The splicing variation is more convenient than the usual way:

> (define-values (inc dec get)
    (let ([x 0])
      (values (lambda ()  ; inc
                (set! x (+ 1 x)))
              (lambda ()  ; dec
                (set! x (- 1 x)))
              (lambda ()  ; get
                x))))

When there are many body forms—and we’re generating them in a macro—the splicing variations can be much easier.